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(params) {
    try {
        const filterConditions = {};

        if (params.display_name) {
            filterConditions.display_name = {
                [Op.like]: `%${params.display_name}%`,
            };
        }

        const questionBanks = await dbSAPPS.QuestionBank.findAll({
            where: filterConditions,
            order: [["modified", "DESC"]],
            include: [{
                model: dbSAPPS.QuestionBankReview,
                as: "questionbankreviews",
                attributes: ["id", "questionbank_id", "description", "min_point", "max_point", "type"],
            }, {
                model: dbSAPPS.Question,
                as: "questions",
                include: [{
                    model: dbSAPPS.Answer,
                    as: "answers",
                }]
            }]
        });

        return {
            questionBanks,
            success: true,
            message: "Question bank loaded successfully!",
        };
    } catch (error) {
        const errorMessage = error.message || "Failed to load question bank!";
        return {
            success: false,
            message: errorMessage,
        };
    }
}

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

    if (params.name) {
        filterConditions.name = {
            [Op.like]: `%${params.name}%`,
        };
    }

    if (params.display_name) {
        filterConditions.display_name = {
            [Op.like]: `%${params.display_name}%`,
        };
    }

    if (params.enabled) {
        filterConditions.enabled = {
            [Op.eq]: params.enabled === "1" ? true : false,
        };
    }

    try {
        const questionBanks = await dbSAPPS.QuestionBank.findAll({
            where: filterConditions,
            order: [["modified", "DESC"]],
            attributes: ["id", "questionbank_id", "description", "min_point", "max_point", "type"],
        });

        return {
            success: true,
            questionBanks,
            message: "Question banks loaded successfully!",
        };
    } catch (error) {
        console.error("Error retrieving designations: ", error);
        const errorMessage = error.message || "Failed to retrieve designations. Please try again later.";
        return {
            success: false,
            message: errorMessage,
        };
    }
}

async function option() {
    try {
        const questionBanks = await dbSAPPS.QuestionBank.findAll({
            attributes: ["id", "display_name", "name"],
            where: { enabled: true },
            order: [["display_name", "ASC"]],
            include: [
                {
                    model: dbSAPPS.QuestionBankReview,
                    as: "questionbankreviews",
                    attributes: ["id", "questionbank_id", "description", "min_point", "max_point"],
                },
            ],
        });

        return {
            success: true,
            questionBanks,
            message: "Question banks loaded successfully!",
        };
    } catch (error) {
        console.error("Error retrieving question banks: ", error);
        const errorMessage = error.message || "Failed to retrieve question banks. Please try again later.";
        return {
            success: false,
            message: errorMessage,
        };
    }
}

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

        return {
            success: true,
            count,
            message: "Question banks loaded successfully!",
        };
    } catch (error) {
        console.error("Error counting question banks: ", error);
        return {
            success: false,
            message: "Failed to retrieve question banks count. Please try again later.",
        };
    }
}

async function create(params) {
    const transaction = await dbSAPPS.sequelize.transaction();
    try {
        if (!params.name || !params.display_name) return { success: false, message: 'Name and display name are required!' };

        const existingName = await dbSAPPS.QuestionBank.findOne({ where: { name: params.name } });
        if (existingName) return { success: false, message: `Name "${params.name}" is already taken.` };

        const existingDisplayName = await dbSAPPS.QuestionBank.findOne({ where: { display_name: params.display_name } });
        if (existingDisplayName) return { success: false, message: `display name "${params.display_name}" is already taken.` };

        const questionBank = await dbSAPPS.QuestionBank.create(params);

        if (params.questionbank_review) {
            params.questionbank_review = JSON.parse(params.questionbank_review);
        }

        if (Array.isArray(params.questionbank_review) && params.questionbank_review.length > 0) {
            const questionBankReviewData = params.questionbank_review.map(questionBankReview => ({
                ...questionBankReview,
                questionbank_id: questionBank.id
            }));
            await dbSAPPS.QuestionBankReview.bulkCreate(questionBankReviewData);
        }

        await transaction.commit();
        return {
            success: true,
            message: 'Question bank has been created!'
        };
    } catch (error) {
        await transaction.rollback();
        const errorMessage = error.message || "An error occurred during question bank creation.";
        return {
            success: false,
            message: errorMessage,
        };
    }
}

async function update(id, params) {
    const transaction = await dbSAPPS.sequelize.transaction();
    try {
        const questionBank = await dbSAPPS.QuestionBank.findByPk(id);
        if (!questionBank) return {
            success: false,
            message: 'Question bank not found!'
        };

        if (params.name && params.name !== questionBank.name) {
            const existingName = await dbSAPPS.QuestionBank.findOne({ where: { name: params.name } });
            if (existingName) {
                if (existingName.id != params.id) {
                    return {
                        success: false,
                        message: `Name "${params.name}" is already taken. Try again!`
                    };
                }
            }
        }

        if (params.display_name && params.display_name !== questionBank.display_name) {
            const existingDisplayName = await dbSAPPS.QuestionBank.findOne({ where: { display_name: params.display_name } });
            if (existingDisplayName) {
                if (existingDisplayName.id != params.id) {
                    return {
                        success: false,
                        message: `Display name "${params.display_name}" is already taken. Try again!`
                    };
                }
            }
        }

        await questionBank.update(params);

        if (params.questionbank_review !== undefined && params.questionbank_review !== null) {
            params.questionbank_review = params?.questionbank_review ? JSON.parse(params?.questionbank_review) : [];
        }

        if (Array.isArray(params.questionbank_review) && params.questionbank_review.length > 0) {
            await dbSAPPS.QuestionBankReview.destroy({ where: { questionbank_id: id }, transaction });
            const questionBankReviewData = params.questionbank_review.map(questionBankReview => ({
                ...questionBankReview,
                questionbank_id: id
            }));
            await dbSAPPS.QuestionBankReview.bulkCreate(questionBankReviewData, { transaction });
        } else {
            await dbSAPPS.QuestionBankReview.destroy({ where: { questionbank_id: id }, transaction });
        }

        await transaction.commit();
        return {
            success: true,
            message: 'Question bank has been updated!'
        };
    } catch (error) {
        await transaction.rollback();
        const errorMessage = error.message || "Failed to update question bank.";
        return {
            success: false,
            message: errorMessage,
        };
    }
}

async function enabled(id, params) {
    try {
        const questionBank = await dbSAPPS.QuestionBank.findByPk(id);
        if (!questionBank)
            return {
                success: false,
                message: "Question bank 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 questionBank.update(updateData);
        return {
            success: true,
            message: "Question bank has been updated!",
        };
    } catch (error) {
        const errorMessage = error.message || "Failed to update question bank.";
        return {
            success: false,
            message: errorMessage,
        };
    }
}

async function _delete(id) {
    try {
        const questionBank = await dbSAPPS.QuestionBank.findByPk(id);
        if (!questionBank) return { success: false, message: "Question bank not found!" };

        await questionBank.destroy();
        return {
            success: true,
            message: "Question bank successfully deleted!",
        };
    } catch (error) {
        const errorMessage = error.message || "Failed to delete question bank.";
        return {
            success: false,
            message: errorMessage,
        };
    }
}
