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

module.exports = {
    filter,
    assignQuestionBanksToCourse,
    getAllCourseQuestionBank,
    deleteCourseQuestionBank
};

async function getQuestionBankIdsByName(names) {
    const questionBanks = await dbSAPPS.QuestionBank.findAll({
        where: {
            display_name: names
        },
        attributes: ['id']
    });

    return questionBanks.map(questionBank => questionBank.id);
}

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

    if (params.course_id) {
        filterConditions.course_id = {
            [Op.eq]: `${params.course_id}`,
        };
    }

    try {
        const courseQuestionBanks = await dbSAPPS.CourseQuestionBank.findAll({
            include: [
                {
                    model: dbSAPPS.Course,
                    as: 'course',
                },
                {
                    model: dbSAPPS.QuestionBank,
                    as: 'questionbank',
                }
            ],
            where: filterConditions,
            order: [['updatedAt', 'DESC']],
        });

        const result = courseQuestionBanks.reduce((acc, courseQuestionBank) => {
            const id = courseQuestionBank.course.id;
            const course_id = courseQuestionBank.course.id;
            const course_title = courseQuestionBank.course.title;
            const questionbank_id = courseQuestionBank.questionbank.id;
            const questionbank_display_name = courseQuestionBank.questionbank.display_name;

            const createdAt = courseQuestionBank.createdAt;
            const updatedAt = courseQuestionBank.updatedAt;

            let existingCourse = acc.find(item => item.course_id === course_id);
            if (!existingCourse) {
                existingCourse = {
                    id,
                    course_id,
                    course_title,
                    questionbank_id,
                    questionbank_display_name,
                    questionbanks: [],
                    questionbanksObject: {},
                    createdAt,
                    updatedAt
                };
                acc.push(existingCourse);
            }

            existingCourse.questionbanks.push(questionbank_display_name);
            existingCourse.questionbanksObject = existingCourse.questionbanks.reduce((acc, display_name) => {
                acc[display_name] = true;
                return acc;
            }, {});

            return acc;
        }, []);

        return {
            courseQuestionBanks: result,
            success: true,
            message: 'Course question banks has been loaded'
        };
    } catch (error) {
        console.error('Error retrieving courses: ', error);
        const errorMessage = error.message || 'Failed to retrieve courses. Please try again later.';
        return {
            success: false,
            message: errorMessage
        };
    }
}

async function assignQuestionBanksToCourse(params) {
    const transaction = await dbSAPPS.sequelize.transaction();
    try {
        const { courseId, lastUsedCourseId, questionBankNames, update } = params;
        if (!courseId || !Array.isArray(questionBankNames) || questionBankNames.length === 0) {
            return {
                success: false,
                message: 'Invalid input. Please ensure that all required fields are provided in the correct format.'
            };
        }

        const course = await dbSAPPS.Course.findByPk(courseId, { transaction });
        if (!course) {
            await transaction.rollback();
            return { success: false, message: 'Course not found!' };
        }

        const courseQuestionBank = await dbSAPPS.CourseQuestionBank.findOne({ where: { course_id: courseId } });
        if (courseQuestionBank && update === false) {
            await transaction.rollback();
            return { success: false, message: 'Course is already assigned to a question bank, please update the assignment if necessary.' };
        }

        if (lastUsedCourseId && update === true) {
            const lastUse = await dbSAPPS.CourseQuestionBank.findOne({ where: { course_id: lastUsedCourseId } });
            if (lastUse) {
                await lastUse.destroy({ transaction });
            }
        }

        const questionBankIds = await getQuestionBankIdsByName(questionBankNames);

        await dbSAPPS.CourseQuestionBank.destroy({ where: { course_id: courseId }, transaction });
        await dbSAPPS.CourseQuestionBank.bulkCreate(
            questionBankIds.map(questionBankId => ({
                course_id: courseId,
                questionbank_id: questionBankId
            })),
            { transaction }
        );
        await transaction.commit();
        return {
            success: true,
            message: 'Question banks have been assigned to the course!'
        };
    } catch (error) {
        await transaction.rollback();
        const errorMessage = error.message || 'Failed to assign question banks to the course.';
        return { success: false, message: errorMessage };
    }
}


async function getAllCourseQuestionBank() {
    try {
        const courseQuestionBanks = await dbSAPPS.CourseQuestionBank.findAll({
            include: [
                {
                    model: dbSAPPS.Course,
                    as: 'course',
                },
                {
                    model: dbSAPPS.QuestionBank,
                    as: 'questionbank',
                },
            ],
            order: [['updatedAt', 'DESC']],
        });

        const result = courseQuestionBanks.reduce((acc, courseQuestionBank) => {
            const id = courseQuestionBank.course.id;
            const course_id = courseQuestionBank.course.id;
            const course_title = courseQuestionBank.course.title;
            const course_description = courseQuestionBank.course.description;
            const questionbank_id = courseQuestionBank.questionbank.id;
            const questionbank_display_name = courseQuestionBank.questionbank.display_name;

            const createdAt = courseQuestionBank.createdAt;
            const updatedAt = courseQuestionBank.updatedAt;

            let existingCourse = acc.find(item => item.course_id === course_id);
            if (!existingCourse) {
                existingCourse = {
                    id,
                    course_id,
                    course_title,
                    course_description,
                    questionbank_id,
                    questionbank_display_name,
                    questionbanks: [],
                    questionbanksObject: {},
                    createdAt,
                    updatedAt
                };
                acc.push(existingCourse);
            }

            existingCourse.questionbanks.push(questionbank_display_name);
            existingCourse.questionbanksObject = existingCourse.questionbanks.reduce((acc, display_name) => {
                acc[display_name] = true;
                return acc;
            }, {});

            return acc;
        }, []);

        return {
            courseQuestionBanks: result,
            success: true,
            message: 'Course question banks has been loaded'
        };
    } catch (error) {
        const errorMessage = error.message || 'Failed to load courses!';
        return {
            success: false,
            message: errorMessage
        };
    }
}

async function deleteCourseQuestionBank(id) {
    const transaction = await dbSAPPS.sequelize.transaction();
    try {
        const course = await dbSAPPS.Course.findByPk(id, { transaction });
        if (!course) {
            await transaction.rollback();
            return { success: false, message: 'Course not found!' };
        }

        const courseQuestionBank = await dbSAPPS.CourseQuestionBank.findAll({
            where: { course_id: id },
            transaction
        });

        if (courseQuestionBank.length === 0) {
            await transaction.rollback();
            return {
                success: false,
                message: 'Course has no associated question bank, so it was not deleted.'
            };
        }

        await dbSAPPS.CourseQuestionBank.destroy({
            where: { course_id: id },
            transaction
        });

        await transaction.commit();
        return {
            success: true,
            message: 'Course and question banks has been deleted!'
        };
    } catch (error) {
        await transaction.rollback();
        const errorMessage = error.message || 'Failed to delete Course and videos.';
        return { success: false, message: errorMessage };
    }
}

