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

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

async function getLogo(params) {
    try {
        const filterConditions = {};

        if (params?.project_id) {
            filterConditions.id = {
                [Op.eq]: params.project_id
            };
        }

        const projects = await dbSAPPS.Project.findAll({
            attributes: ['id', 'name', 'display_name', 'project_logo', 'project_logo_secondary', 'project_logo_navbar'],
            where: filterConditions,
            order: [['modified', 'DESC']],

        });

        return {
            projects,
            success: true,
            message: 'Projects has been loaded!'
        };
    } catch (error) {
        const errorMessage = error.message || 'Failed to load project logo!';
        return {
            success: false,
            message: errorMessage
        };
    }
}

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

        if (params?.projectsId) {
            filterConditions.id = {
                [Op.in]: params?.projectsId
            };
        }

        const projects = await dbSAPPS.Project.findAll({
            where: filterConditions,
            order: [['modified', 'DESC']],
            include: [{
                model: dbSAPPS.ProjectTeam,
                as: 'projectteams'
            }]
        });

        return {
            projects,
            success: true,
            message: 'Projects has been loaded!'
        };
    } catch (error) {
        const errorMessage = error.message || 'Failed to load projects!';
        return {
            success: false,
            message: errorMessage
        };
    }
}

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

    if (params?.projectsId) {
        filterConditions.id = {
            [Op.in]: params?.projectsId
        };
    }

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

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

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

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

    try {
        const projects = await dbSAPPS.Project.findAll({
            where: filterConditions,
            order: [['modified', 'DESC']],
            include: [{
                model: dbSAPPS.ProjectTeam,
                as: 'projectteams'
            }]
        });

        return {
            projects,
            success: true,
            message: 'Projects has been loaded!'
        };
    } catch (error) {
        console.error('Error retrieving projects: ', error);
        const errorMessage = error.message || 'Failed to retrieve projects. Please try again later.';
        return {
            success: false,
            message: errorMessage
        };
    }
}

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

        if (params?.projectsId) {
            filterConditions.id = {
                [Op.in]: params?.projectsId
            };
        }

        filterConditions.enabled = {
            [Op.eq]: true
        };

        const projects = await dbSAPPS.Project.findAll({
            attributes: ['id', 'name', 'display_name', 'project_logo'],
            where: filterConditions,
            order: [['name', 'ASC']],
        });

        return {
            projects,
            success: true,
            message: 'Projects has been loaded!'
        };
    } catch (error) {
        console.error('Error retrieving projects: ', error);
        const errorMessage = error.message || 'Failed to retrieve projects. Please try again later.';
        return {
            success: false,
            message: errorMessage
        };
    }
}

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

        return {
            count,
            success: true,
            message: 'Projects has been loaded!'
        };
    } catch (error) {
        console.error('Error retrieving projects: ', error);
        const errorMessage = error.message || 'Failed to retrieve projects. Please try again later.';
        return {
            success: false,
            message: errorMessage
        };
    }
}

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

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

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

        const existingSlugName = await dbSAPPS.Project.findOne({ where: { slug_name: params.slug_name } });
        if (existingSlugName) return { success: false, message: `Slug name "${params.slug_name}" is already taken.` };

        const project = await dbSAPPS.Project.create(params, { transaction });

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

        if (Array.isArray(params.project_team) && params.project_team.length > 0) {
            const projectTeamData = params.project_team.map(projectTeam => ({
                ...projectTeam,
                project_id: project.id
            }));
            await dbSAPPS.ProjectTeam.bulkCreate(projectTeamData, { transaction });
        }

        await transaction.commit();
        return {
            success: true,
            message: 'Project has been created!'
        };
    } catch (error) {
        await transaction.rollback();
        const errorMessage = error.message || 'An error occurred during creating project.';
        return {
            success: false,
            message: errorMessage
        };
    }
}

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

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

            }
        }

        if (params.display_name && params.display_name !== project.display_name) {
            const existingDisplayName = await dbSAPPS.Project.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!`
                    };
                }
            }
        }

        if (params.slug_name && params.slug_name !== project.slug_name) {
            const existingSlugName = await dbSAPPS.Project.findOne({ where: { slug_name: params.slug_name } });
            if (existingSlugName) {
                if (existingSlugName.id != params.id) {
                    return {
                        success: false,
                        message: `Slug name "${params.slug_name}" is already taken. Try again!`
                    };
                }
            }
        }

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

        if (Array.isArray(params.project_team) && params.project_team.length > 0) {
            await dbSAPPS.ProjectTeam.destroy({ where: { project_id: id }, transaction });
            const projectTeamData = params.project_team.map(projectTeam => ({
                ...projectTeam,
                project_id: id
            }));
            await dbSAPPS.ProjectTeam.bulkCreate(projectTeamData, { transaction });
        }

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

async function enabled(id, params) {
    try {
        const project = await dbSAPPS.Project.findByPk(id);
        if (!project) return {
            success: false,
            message: 'Project 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;

        // debug
        // console.log('id', id);
        // console.log('params', params);
        // console.log('updateData', updateData)

        await project.update(updateData);
        return {
            success: true,
            message: 'Project has been updated!'
        };
    } catch (error) {
        const errorMessage = error.message || 'Failed to update project.';
        return {
            success: false,
            message: errorMessage
        };
    }
}

async function _delete(id) {
    try {
        const project = await dbSAPPS.Project.findByPk(id);
        if (!project) return { success: false, message: 'Project not found!' };

        await project.destroy();
        return {
            success: true,
            message: 'Project has been deleted!'
        };
    } catch (error) {
        const errorMessage = error.message || 'Failed to delete project.';
        return {
            success: false,
            message: errorMessage
        };
    }
}
