const dbSAPPS = require('../../helpers/db');
require('dotenv').config();
const { Op } = require('sequelize');

module.exports = {
    create,
    getAll,
    option,
    count,
    update,
    TypeEnabled,
    delete: _delete,

    getAllSubType,
    createSubType,
    optionSubType,
    countSubType,
    updateSubType,
    SubTypeEnabled,
    deleteSubType,

};


const formatWithModifier = async (datas) => {
    return Promise.all(
        datas.map(async (data) => {
            const modifier = await dbSAPPS.User.findOne({
                where: {
                    id: data.modified_by
                },
                attributes: ['full_name']
            });

            return {
                ...data,
                modifier: modifier?.full_name
            };
        })
    );
};

async function getAll(params) {
    try {
        // filter
        const filterConditions = {};

         if (params.companiesId) {
            filterConditions.company_id = {
                [Op.in]: params.companiesId
            };
        }

        const datas = await dbSAPPS.GimmickReqType.findAll({
            where: filterConditions,
            order: [['modified', 'DESC']],
            include: [
                {
                    model: dbSAPPS.Company,
                    as: 'company',
                    attributes: ['id', 'display_name'],
                },
                {
                    model: dbSAPPS.GimmickReqSubType,
                    as: 'subtypes',
                    attributes: ['id', 'display_name'],
                }
            ]
        });

        const formattedData = await formatWithModifier(datas);

        const result = formattedData.map(data => ({
            ...data.dataValues,
            modifier: data.modifier
        }));

        return {
            datas: result,
            success: true,
            message: 'Loaded successfully!'
        };
    } catch (error) {
        const errorMessage = error?.message || 'Failed to load, please try again!';
        return {
            success: false,
            message: errorMessage,
        };
    }
}

async function option(params) {
    try {
        // filter
        const filterConditions = {};

         if (params.companiesId) {
            filterConditions.company_id = {
                [Op.in]: params.companiesId
            };
        }

        let datas = [];
        datas = await dbSAPPS.GimmickReqType.findAll({
            where: filterConditions,
            attributes: ['id',  'display_name'],
            order: [[ 'display_name','ASC']],
            include: [
                {
                    model: dbSAPPS.GimmickReqSubType,
                    as: 'subtypes',
                    attributes: ['id', 'display_name'],
                }
            ]
        });

        return {
            datas,
            success: true,
            message: 'Loaded successfully!'
        };
    } catch (error) {
        const errorMessage = error?.message || 'Failed to load, please try again!';
        return {
            success: false,
            message: errorMessage
        };
    }
}

async function count(params) {
    try {
        // filter
        const filterConditions = {};

        const count = await dbSAPPS.GimmickReqType.count({
            where: filterConditions
        });


        return {
            count,
            success: true,
            message: 'Loaded successfully!'
        };
    } catch (error) {
        const errorMessage = error?.message || 'Failed to load, please try again!';
        return {
            success: false,
            message: errorMessage
        };
    }
}

async function create(params) {
    const transaction = await dbSAPPS.sequelize.transaction();
    try {
        // validate existing
        const existingDisplayName = await dbSAPPS.GimmickReqType.findOne({
            where: { display_name: params.display_name },
            transaction
        });
        if (existingDisplayName) {
            return {
                success: false,
                message: `"${params.display_name}" is already taken.`
            };
        }

        // save
        await dbSAPPS.GimmickReqType.create(params, { transaction });

        await transaction.commit();
        return {
            success: true,
            message: 'Saved successfully!'
        };
    } catch (error) {
        await transaction.rollback();
        const errorMessage = error?.message || 'Failed to save, please try again!';
        return {
            success: false,
            message: errorMessage
        };
    }
}

async function update(id, params) {
    const transaction = await dbSAPPS.sequelize.transaction();
    try {
        // validate existing
        const data = await dbSAPPS.GimmickReqType.findByPk(id);
        if (!data) return { success: false, message: 'ID not found!' };

        // validate existing
        const existingDisplayName = await dbSAPPS.GimmickReqType.findOne({
            where: {
                display_name: params.display_name,
                id: {
                    [Op.ne]: id
                }
            },
            transaction
        });
        if (existingDisplayName) {
            return {
                success: false,
                message: `"${params.display_name}" is already taken.`
            };
        }

        // save
        await data.update(params, { transaction });

        await transaction.commit();
        return {
            success: true,
            message: 'Saved successfully!'
        };
    } catch (error) {
        await transaction.rollback();
        const errorMessage = error?.message || 'Failed to save, please try again!';
        return {
            success: false,
            message: errorMessage
        };
    }
}

async function _delete(id) {
    const transaction = await dbSAPPS.sequelize.transaction();
    try {
        // validate existing
        const data = await dbSAPPS.GimmickReqType.findByPk(id, { transaction });
        if (!data) return { success: false, message: 'ID not found!' };

        // delete
        await data.destroy({ transaction });

        await transaction.commit();
        return {
            success: true,
            message: 'Deleted successfully!'
        };
    } catch (error) {
        await transaction.rollback();
        const errorMessage = error?.message || 'Failed to delete, please try again!';
        return {
            success: false,
            message: errorMessage
        };
    }
}

async function TypeEnabled(id, params) {
  try {
    const data = await dbSAPPS.GimmickReqType.findByPk(id);
    if (!data)
      return {
        success: false,
        message: "Data not found!",
      };

    const updateData = {};
    updateData.enabled = params.enabled;
    if (params.modified_by) updateData.modified_by = params.modified_by;
    if (params.modified) updateData.modified = params.modified;

    await data.update(updateData);

    return {
      success: true,
      message: "Data has been updated!",
    };
  } catch (error) {
    const errorMessage = error.message || "Failed to Update.";
    return {
      success: false,
      message: errorMessage,
    };
  }
}


// # SUB TYPE
async function getAllSubType(params) {
    try {
        // filter
        const filterConditions = {};
          if (params.companiesId) {
            filterConditions.company_id = {
                [Op.in]: params.companiesId
            };
        }
        const datas = await dbSAPPS.GimmickReqSubType.findAll({
            where: filterConditions,
            order: [['modified', 'DESC']],
            include: [
                {
                    model: dbSAPPS.GimmickReqType,
                    as: 'reqtype',
                    attributes: ['id', 'display_name'],
                }
            ]
        });

        const formattedData = await formatWithModifier(datas);

        const result = formattedData.map(data => ({
            ...data.dataValues,
            modifier: data.modifier
        }));

        return {
            datas: result,
            success: true,
            message: 'Loaded successfully!'
        };
    } catch (error) {
        const errorMessage = error?.message || 'Failed to load, please try again!';
        return {
            success: false,
            message: errorMessage,
        };
    }
}

async function optionSubType(params) {
    try {
        // filter
        const filterConditions = {};

        let datas = [];
        datas = await dbSAPPS.GimmickReqSubType.findAll({
            where: filterConditions,
            attributes: ['id',  'display_name'],
            order: [[ 'display_name','ASC']]
        });

        return {
            datas,
            success: true,
            message: 'Loaded successfully!'
        };
    } catch (error) {
        const errorMessage = error?.message || 'Failed to load, please try again!';
        return {
            success: false,
            message: errorMessage
        };
    }
}

async function countSubType(params) {
    try {
        // filter
        const filterConditions = {};

        const count = await dbSAPPS.GimmickReqSubType.count({
            where: filterConditions
        });


        return {
            count,
            success: true,
            message: 'Loaded successfully!'
        };
    } catch (error) {
        const errorMessage = error?.message || 'Failed to load, please try again!';
        return {
            success: false,
            message: errorMessage
        };
    }
}

async function createSubType(params) {
    const transaction = await dbSAPPS.sequelize.transaction();
    try {
        // validate existing
        const existingDisplayName = await dbSAPPS.GimmickReqSubType.findOne({
            where: { display_name: params.display_name, gimmickreqtype_id: params.gimmickreqtype_id },
            transaction
        });
        if (existingDisplayName) {
            return {
                success: false,
                message: `"${params.display_name}" is already taken.`
            };
        }

        // save
        await dbSAPPS.GimmickReqSubType.create(params, { transaction });

        await transaction.commit();
        return {
            success: true,
            message: 'Saved successfully!'
        };
    } catch (error) {
        await transaction.rollback();
        const errorMessage = error?.message || 'Failed to save, please try again!';
        return {
            success: false,
            message: errorMessage
        };
    }
}

async function updateSubType(id, params) {
    const transaction = await dbSAPPS.sequelize.transaction();
    try {
        // validate existing
        const data = await dbSAPPS.GimmickReqSubType.findByPk(id);
        if (!data) return { success: false, message: 'ID not found!' };

        // validate existing
        const existingDisplayName = await dbSAPPS.GimmickReqSubType.findOne({
            where: {
                display_name: params.display_name,
                gimmickreqtype_id: params.gimmickreqtype_id,
                id: {
                    [Op.ne]: id
                }
            },
            transaction
        });
        if (existingDisplayName) {
            return {
                success: false,
                message: `"${params.display_name}" is already taken.`
            };
        }

        // save
        await data.update(params, { transaction });

        await transaction.commit();
        return {
            success: true,
            message: 'Saved successfully!'
        };
    } catch (error) {
        await transaction.rollback();
        const errorMessage = error?.message || 'Failed to save, please try again!';
        return {
            success: false,
            message: errorMessage
        };
    }
}

async function deleteSubType(id) {
    const transaction = await dbSAPPS.sequelize.transaction();
    try {
        // validate existing
        const data = await dbSAPPS.GimmickReqSubType.findByPk(id, { transaction });
        if (!data) return { success: false, message: 'ID not found!' };

        // delete
        await data.destroy({ transaction });

        await transaction.commit();
        return {
            success: true,
            message: 'Deleted successfully!'
        };
    } catch (error) {
        await transaction.rollback();
        const errorMessage = error?.message || 'Failed to delete, please try again!';
        return {
            success: false,
            message: errorMessage
        };
    }
}

async function SubTypeEnabled(id, params) {
  try {
    const data = await dbSAPPS.GimmickReqSubType.findByPk(id);
    if (!data)
      return {
        success: false,
        message: "Data not found!",
      };

    const updateData = {};
    updateData.enabled = params.enabled;
    if (params.modified_by) updateData.modified_by = params.modified_by;
    if (params.modified) updateData.modified = params.modified;

    await data.update(updateData);

    return {
      success: true,
      message: "Data has been updated!",
    };
  } catch (error) {
    const errorMessage = error.message || "Failed to Update.";
    return {
      success: false,
      message: errorMessage,
    };
  }
}
