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

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

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

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

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

        const andConditions = [];
        if (params.q) {
            andConditions.push({
                [Op.or]: [
                    { name: { [Op.iLike]: `%${params.q}%` } },
                    { display_name: { [Op.iLike]: `%${params.q}%` } },
                    { "$company.display_name$": { [Op.iLike]: `%${params.q}%` } },
                ],
            });
        }

        const whereClause = {
            ...filterConditions,
            ...(andConditions.length ? { [Op.and]: andConditions } : {}),
        };

        const rawSize = parseInt(params?.pageSize, 10);
        const pageSize = Number.isFinite(rawSize) && rawSize > 0 ? Math.min(rawSize, 100) : 10;
        const rawIndex = parseInt(params?.pageIndex, 10);
        const pageIndex = Number.isFinite(rawIndex) && rawIndex >= 0 ? rawIndex : 0;

        const allowedSortBy = ["modified", "display_name", "name"];
        const sortBy = allowedSortBy.includes(params?.sortBy) ? params.sortBy : "modified";
        const sortDir = (params?.sortDir || "DESC").toString().toUpperCase() === "ASC" ? "ASC" : "DESC";

        const { rows, count } = await dbSAPPS.Team.findAndCountAll({
            where: whereClause,
            order: [[sortBy, sortDir]],
            offset: pageIndex * pageSize,
            limit: pageSize,
            include: [
                {
                    model: dbSAPPS.Company,
                    as: "company",
                    attributes: ["id", "display_name", "name"],
                },
                {
                    model: dbSAPPS.User,
                    as: "modifier",
                    attributes: ["full_name"],
                },
            ],
        });

        const teams = rows.map((team) => ({
            ...team.dataValues,
            company_name: team?.company?.display_name,
            modifier: team?.modifier?.full_name,
        }));

        return {
            teams,
            totalCount: count,
            pageIndex,
            pageSize,
            sortBy,
            sortDir,
            success: true,
            message: "Loaded successfully!",
        };
    } catch (error) {
        return { success: false, message: error?.message || "Failed to load!" };
    }
}

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

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

        let options = await dbSAPPS.Team.findAll({
            attributes: ["id", "display_name", "name", "company_id"],
            where: filterConditions,
            order: [["name", "ASC"]],
            include: [
                {
                    model: dbSAPPS.Company,
                    as: "company",
                    attributes: ["id", "display_name", "name"],
                },
            ],
        });

        options = options.map((opt) => ({
            ...opt.dataValues,
            company_name: opt?.company?.display_name,
        }));

        return { options, success: true, message: "Loaded successfully!" };
    } catch (error) {
        return { success: false, message: error?.message || "Failed to load!" };
    }
}

async function count() {
    try {
        const count = await dbSAPPS.Team.count({ where: { enabled: true } });
        return { count, success: true, message: "Loaded successfully!" };
    } catch (error) {
        return { success: false, message: error?.message || "Failed to load!" };
    }
}

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

        if (params.enabled === undefined) params.enabled = true;
        await dbSAPPS.Team.create(params, { transaction });
        await transaction.commit();
        return { success: true, message: "Saved successfully!" };
    } catch (error) {
        await transaction.rollback();
        return { success: false, message: error?.message || "Failed to save!" };
    }
}

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

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

        await team.update(params, { transaction });
        await transaction.commit();
        return { success: true, message: "Saved successfully!" };
    } catch (error) {
        await transaction.rollback();
        return { success: false, message: error?.message || "Failed to save!" };
    }
}

async function enabled(id, params) {
    const transaction = await dbSAPPS.sequelize.transaction();
    try {
        const team = await dbSAPPS.Team.findByPk(id);
        if (!team) return { success: false, message: "ID not found!" };

        await team.update({
            enabled: params.enabled,
            modified_by: params.modified_by,
            modified: params.modified
        }, { transaction });

        await transaction.commit();
        return { success: true, message: "Saved successfully!" };
    } catch (error) {
        await transaction.rollback();
        return { success: false, message: error?.message || "Failed to save!" };
    }
}

async function _delete(id) {
    const transaction = await dbSAPPS.sequelize.transaction();
    try {
        const team = await dbSAPPS.Team.findByPk(id, { transaction });
        if (!team) return { success: false, message: "ID not found!" };

        await team.destroy({ transaction });
        await transaction.commit();
        return { success: true, message: "Deleted successfully!" };
    } catch (error) {
        await transaction.rollback();
        return { success: false, message: error?.message || "Failed to delete!" };
    }
}
