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

module.exports = {
    filter,
    assignItemGroupsToTerritory,
    getAllTerritoryItemGroup,
    deleteTerritoryItemGroup
};

async function getItemGroupsIdsByName(names) {
    const itemgroups = await dbSAPPS.ItemGroup.findAll({
        where: {
            display_name: names
        },
        attributes: ['id']
    });

    return itemgroups.map(itemgroup => itemgroup.id);
}

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

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

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

    try {
        const territoryItemGroups = await dbSAPPS.TerritoryItemGroup.findAll({
            include: [
                {
                    model: dbSAPPS.Territory,
                    as: 'territory',
                },
                {
                    model: dbSAPPS.ItemGroup,
                    as: 'itemgroup',
                    include: [
                        {
                            model: dbSAPPS.Item,
                            as: 'items',
                            attributes: ['id', 'display_name', 'therapy_class', 'valid_from', 'valid_to', 'price'],
                            include: [
                                {
                                    model: dbSAPPS.ItemCompetitor,
                                    as: 'itemcompetitors',
                                    attributes: ['id', 'display_name'],

                                }
                            ]
                        }, 
                      
                    ]
                }
            ],
            where: filterConditions,
            order: [['updatedAt', 'DESC']],
        });

        const result = territoryItemGroups.reduce((acc, territoryItemGroup) => {
            const id = territoryItemGroup.territory.id;
            const territory_id = territoryItemGroup.territory.id;
            const territory_name = territoryItemGroup.territory.display_name;
            const territory_code = territoryItemGroup.territory.code;
            const itemgroup_id = territoryItemGroup.itemgroup.id;
            const itemgroup_name = territoryItemGroup.itemgroup.display_name;

            const createdAt = territoryItemGroup.createdAt;
            const updatedAt = territoryItemGroup.updatedAt;

            let existingTerritory = acc.find(item => item.territory_id === territory_id);
            if (!existingTerritory) {
                existingTerritory = {
                    id,
                    territory_id,
                    territory_name,
                    territory_code,
                    itemgroup_name,
                    itemGroupIds: [],
                    itemgroup_items : [],
                    itemGroups: [],
                    itemGroupsObject: {},
                    createdAt,
                    updatedAt
                };
                acc.push(existingTerritory);
            }

            existingTerritory.itemGroups.push(itemgroup_name);
            existingTerritory.itemgroup_items.push(...territoryItemGroup.itemgroup.items);
            existingTerritory.itemGroupIds.push(itemgroup_id);
            existingTerritory.itemGroupsObject = existingTerritory.itemGroups.reduce((acc, display_name) => {
                acc[display_name] = true;
                return acc;
            }, {});


            return acc;
        }, []);

        return {
            territoryItemGroups: result,
            success: true,
            message: 'Territory item groups has been loaded'
        };
    } catch (error) {
        console.error('Error retrieving territory item groups: ', error);
        const errorMessage = error.message || 'Failed to retrieve territory item groups. Please try again later.';
        return {
            success: false,
            message: errorMessage
        };
    }
}

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

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

        const territoryItemGroup = await dbSAPPS.TerritoryItemGroup.findOne({ where: { territory_id: territoryId } });
        if (territoryItemGroup && update === false) {
            await transaction.rollback();
            return { success: false, message: 'Territory is already assigned to a item group, please update the assignment if necessary.' };
        }

        if (lastUsedTerritoryId && update === true) {
            const lastUse = await dbSAPPS.TerritoryItemGroup.findOne({ where: { territory_id: lastUsedTerritoryId } });
            if (lastUse) {
                await lastUse.destroy({ transaction });
            }
        }

        const itemGroupIds = await getItemGroupsIdsByName(itemGroupNames);

        await territory.setItemgroups(itemGroupIds, { transaction });
        await transaction.commit();
        return {
            success: true,
            message: 'Item groups have been assigned to the territory!'
        };
    } catch (error) {
        await transaction.rollback();
        const errorMessage = error.message || 'Failed to assign item groups to the territory.';
        return { success: false, message: errorMessage };
    }
}

async function getAllTerritoryItemGroup() {
    try {
        const territoryItemGroup = await dbSAPPS.TerritoryItemGroup.findAll({
            include: [
                {
                    model: dbSAPPS.Territory,
                    as: 'territory',
                },
                {
                    model: dbSAPPS.ItemGroup,
                    as: 'itemgroup',
                }
            ],
            order: [['updatedAt', 'DESC']],
        });

        const result = territoryItemGroup.reduce((acc, territoryItemGroup) => {
            const id = territoryItemGroup.territory.id;
            const territory_id = territoryItemGroup.territory_id;
            const territory_name = territoryItemGroup.territory.display_name;
            const territory_code = territoryItemGroup.territory.code;
            const itemgroup_name = territoryItemGroup.itemgroup.display_name;

            const createdAt = territoryItemGroup.createdAt;
            const updatedAt = territoryItemGroup.updatedAt;

            let existingTerritory = acc.find(item => item.territory_id === territory_id);
            if (!existingTerritory) {
                existingTerritory = {
                    id,
                    territory_id,
                    territory_name,
                    territory_code,
                    itemgroup_name,
                    itemGroups: [],
                    itemGroupsObject: {},
                    createdAt,
                    updatedAt
                };
                acc.push(existingTerritory);
            }

            existingTerritory.itemGroups.push(itemgroup_name);
            existingTerritory.itemGroupsObject = existingTerritory.itemGroups.reduce((acc, display_name) => {
                acc[display_name] = true;
                return acc;
            }, {});

            return acc;
        }, []);

        return {
            territoryItemGroups: result,
            success: true,
            message: 'Territory item groups has been loaded'
        };
    } catch (error) {
        const errorMessage = error.message || 'Failed to load Territory item groups!';
        return {
            success: false,
            message: errorMessage
        };
    }
}

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

        const territoryItemGroup = await dbSAPPS.TerritoryItemGroup.findAll({
            where: { territory_id: id },
            transaction
        });

        if (territoryItemGroup.length === 0) {
            await transaction.rollback();
            return {
                success: false,
                message: 'Territory has no associated item groups, so it was not deleted.'
            };
        }

        await dbSAPPS.TerritoryItemGroup.destroy({
            where: { territory_id: id },
            transaction
        });

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