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

module.exports = {
    getAll,
    filter,
    option,
    count,
    create,
    update,
    enabled,
    delete: _delete,
};

async function getAll() {
    try {
        const goodReceipts = await dbSAPPS.GoodReceipt.findAll({
            order: [["modified", "DESC"]],
        });

        const goodReceiptsPromises = goodReceipts.map(async (goodReceipt) => {
            const employeePromises = [];
            if (goodReceipt.submitted_by) {
                employeePromises.push(
                    dbSAPPS.Employee.findOne({
                        where: { id: goodReceipt.submitted_by },
                        attributes: ["id", "employee_name", "company_id"],
                        include: [
                            {
                                model: dbSAPPS.Company,
                                as: "company",
                                attributes: ["id", "display_name"],
                            },
                        ],
                    })
                );
            }

            if (goodReceipt.received_by) {
                employeePromises.push(
                    dbSAPPS.Employee.findOne({
                        where: { id: goodReceipt.received_by },
                        attributes: ["id", "employee_name", "company_id"],
                        include: [
                            {
                                model: dbSAPPS.Company,
                                as: "company",
                                attributes: ["id", "display_name"],
                            },
                        ],
                    })
                );
            }

            const [submittedBy, receivedBy] = await Promise.all(employeePromises);

            return {
                ...goodReceipt.dataValues,
                submitted_by_name: submittedBy ? submittedBy.employee_name : null,
                received_by_name: receivedBy ? receivedBy.employee_name : null,
                submitted_company_name: submittedBy ? submittedBy.company.display_name : null,
                received_company_name: receivedBy ? receivedBy.company.display_name : null,
            };
        });

        const goodReceiptsWithEmployeeNames = await Promise.all(goodReceiptsPromises);

        return {
            goodReceipts: goodReceiptsWithEmployeeNames,
            success: true,
            message: "good receipts loaded successfully!",
        };
    } catch (error) {
        const errorMessage = error.message || "Failed to load good receipts!";
        return {
            success: false,
            message: errorMessage,
        };
    }
}

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

    try {
        const goodReceipts = await dbSAPPS.GoodReceipt.findAll({
            where: filterConditions,
            order: [["modified", "DESC"]],
        });

        return {
            success: true,
            goodReceipts,
            message: "good receipts loaded successfully!",
        };
    } catch (error) {
        const errorMessage = error.message || "Failed to retrieve good receipts. Please try again later.";
        return {
            success: false,
            message: errorMessage,
        };
    }
}

async function option() {
    try {
        const goodReceipts = await dbSAPPS.GoodReceipt.findAll({
            attributes: ["id", "code", "display_name"],
            where: { enabled: true },
            order: [["display_name", "ASC"]],
        });

        return {
            success: true,
            goodReceipts,
            message: "good receipts loaded successfully!",
        };
    } catch (error) {
        const errorMessage = error.message || "Failed to retrieve good receipts. Please try again later.";
        return {
            success: false,
            message: errorMessage,
        };
    }
}

async function count() {
    try {
        const count = await dbSAPPS.GoodReceipt.count({
            where: { enabled: true },
        });

        return {
            success: true,
            count,
            message: "good receipts loaded successfully!",
        };
    } catch (error) {
        const errorMessage = error.message || "Failed to retrieve good receipts. Please try again later.";
        return {
            success: false,
            message: errorMessage,
        };
    }
}

async function create(params) {
    try {
        if (!params.material_request_name || !params.purchase_order_name || !params.received_date || !params.item_code || !params.item_name)
            return {
                success: false,
                message: "material request name, purchase order name, received date, item code, and item name are required!",
            };

        const existing = await dbSAPPS.GoodReceipt.findOne({
            where: {
                material_request_name: params.material_request_name,
                purchase_order_name: params.purchase_order_name,
                received_date: params.received_date,
                item_code: params.item_code,
                item_name: params.item_name
            },
        });

        if (existing)
            return {
                success: false,
                message: `good receipt with material request name "${params.material_request_name}", purchase order name "${params.purchase_order_name}", received date "${params.received_date}", item code "${params.item_code}", and item name "${params.item_name}" is already taken.`,
            };

        if (!params.enabled) params.enabled = true;
        await dbSAPPS.GoodReceipt.create(params);
        return {
            success: true,
            message: "good receipt data has been successfully added!",
        };
    } catch (error) {
        const errorMessage = error.message || "An error occurred during create good receipt processing.";
        return {
            success: false,
            message: errorMessage,
        };
    }
}

async function update(id, params) {
    try {
        const goodReceipt = await dbSAPPS.GoodReceipt.findByPk(id);
        if (!goodReceipt)
            return {
                success: false,
                message: "good receipt not found!",
            };


        const existing = await dbSAPPS.GoodReceipt.findOne({
            where: {
                material_request_name: params.material_request_name,
                purchase_order_name: params.purchase_order_name,
                received_date: params.received_date,
                item_code: params.item_code,
                item_name: params.item_name
            }
        });
        
        if (existing) {
            if (existing.id != params.id) {
                return {
                    success: false,
                    message: `good receipt with material request name "${params.material_request_name}", purchase order name "${params.purchase_order_name}", received date "${params.received_date}", item code "${params.item_code}", and item name "${params.item_name}" is already taken.`,
                };
            }
        }

        await goodReceipt.update(params);
        return {
            success: true,
            message: "Data good receipt has been saved!",
        };
    } catch (error) {
        const errorMessage = error.message || "Failed to update good receipt data.";
        return {
            success: false,
            message: errorMessage,
        };
    }
}

async function enabled(id, params) {
    try {
        const goodReceipt = await dbSAPPS.GoodReceipt.findByPk(id);
        if (!goodReceipt)
            return {
                success: false,
                message: "good receipt 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 goodReceipt.update(updateData);

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

async function _delete(id) {
    try {
        const goodReceipt = await dbSAPPS.GoodReceipt.findByPk(id);
        if (!goodReceipt) return { success: false, message: "good receipt not found!" };

        await goodReceipt.destroy();
        return {
            success: true,
            message: "Good receipt successfully deleted!",
        };
    } catch (error) {
        const errorMessage = error.message || "Failed to delete good receipt.";
        return {
            success: false,
            message: errorMessage,
        };
    }
}

