import { Request, Response } from 'express';
import { Op } from 'sequelize';
import { syncDistrictsByRegion, syncDistrictsByZone, syncLocationManagers, syncRegionManager, syncZoneManager } from './syncHierarchy.service.js';
import db from '../../database/models/index.js';
import {
    ROLES,
    SYSTEM_AUDIT_MODULES,
    SYSTEM_AUDIT_ACTIONS
} from '../../common/config/constants.js';
import { resolveManagerCode } from '../../services/userRoleCode.service.js';
import { logSystemAudit } from '../../services/systemAuditLog.service.js';
const { User } = db;

const deriveZonePrefix = (zone: any): string => {
    const rawCode = String(zone?.code || '').trim().toUpperCase();
    if (/^[A-Z]{2,4}$/.test(rawCode)) return rawCode;

    const words = String(zone?.name || '')
        .trim()
        .toUpperCase()
        .split(/[\s_-]+/)
        .filter(Boolean);
    if (words.length >= 2) return `${words[0][0]}${words[1][0]}`;
    if (words.length === 1) return words[0].slice(0, 2) || 'RG';
    return 'RG';
};

const nextRegionCode = async (zoneId: string, excludeRegionId?: string): Promise<string> => {
    const zone = await db.Zone.findByPk(zoneId, { attributes: ['id', 'name', 'code'] });
    if (!zone) throw new Error('Zone not found');

    const prefix = deriveZonePrefix(zone);
    const where: any = {
        zoneId,
        code: { [Op.iLike]: `${prefix}-R%` }
    };
    if (excludeRegionId) where.id = { [Op.ne]: excludeRegionId };

    const existing = await db.Region.findAll({
        where,
        attributes: ['code']
    });

    let maxSeq = 0;
    for (const row of existing as any[]) {
        const match = String(row.code || '').match(new RegExp(`^${prefix}-R(\\d+)$`, 'i'));
        if (!match) continue;
        const seq = Number(match[1]);
        if (Number.isFinite(seq) && seq > maxSeq) maxSeq = seq;
    }

    return `${prefix}-R${maxSeq + 1}`;
};

// --- Areas (Granular Locations) ---
export const getAreas = async (req: Request, res: Response) => {
    try {
        let search = req.query.search as string;
        let page = (req.query.page || 1) as any;
        let limit = (req.query.limit || 10) as any;
        
        const checkNested = (obj: any) => {
            if (!obj || typeof obj !== 'object') return;
            if (!search && obj.search) search = obj.search;
            if (page === 1 && obj.page) page = obj.page;
            if (limit === 10 && obj.limit) limit = obj.limit;
        };

        checkNested(req.query.params);
        
        const isAll = limit === 'all' || limit === -1 || limit === '-1';
        
        page = Number(page || 1);
        limit = isAll ? null : Number(limit || 10);
        const offset = isAll ? null : (page - 1) * limit;
        
        const where: any = {};
        if (search) {
            where[Op.or] = [
                { name: { [Op.iLike]: `%${search}%` } },
                { city: { [Op.iLike]: `%${search}%` } },
                { '$district.name$': { [Op.iLike]: `%${search}%` } }
            ];
        }

        const stateId = req.query.stateId as string;
        const zoneId = req.query.zoneId as string;
        const regionId = req.query.regionId as string;
        const isOpportunity = req.query.isOpportunity as string || req.query.isActive as string;

        if (stateId && stateId !== 'all') where['$district.stateId$'] = stateId;
        if (zoneId && zoneId !== 'all') where['$district.zoneId$'] = zoneId;
        if (regionId && regionId !== 'all') where['$district.regionId$'] = regionId;
        
        if (isOpportunity === 'true' || isOpportunity === 'false') {
            where.isOpportunity = isOpportunity === 'true';
        }

        const { count, rows: areas } = await db.Location.findAndCountAll({
            where,
            include: [
                {
                    model: db.District,
                    as: 'district',
                    include: [
                        { model: db.Zone, as: 'zone', attributes: ['name'] },
                        { model: db.Region, as: 'region', attributes: ['name'] },
                        { model: db.State, as: 'state', attributes: ['name'] }
                    ]
                }
            ],
            order: [['name', 'ASC']],
            limit: limit === null ? undefined : Number(limit),
            offset: offset === null ? undefined : Number(offset),
            distinct: true,
            subQuery: false
        });
        
        const result = areas.map((a: any) => {
            const d = a.district || {};
            return {
                ...a.toJSON(),
                districtName: d.name || 'N/A',
                zoneName: d.zone?.name || 'UNKNOWN',
                regionName: d.region?.name || 'UNKNOWN',
                stateName: d.state?.name || 'UNKNOWN'
            };
        });

        res.json({ 
            success: true, 
            data: result,
            pagination: {
                total: count,
                page: Number(page),
                limit: isAll ? count : Number(limit),
                totalPages: isAll ? 1 : Math.ceil(count / Number(limit))
            }
        });
    } catch (error) {
        console.error('Get areas error:', error);
        res.status(500).json({ success: false, message: 'Error fetching areas' });
    }
};

// --- Districts (Territory Entities) ---
export const getDistricts = async (req: Request, res: Response) => {
    try {
        const { search, page = 1, limit = 10, stateId, zoneId, regionId, isActive, isOpportunity } = req.query as any;
        const isAll = limit === 'all' || limit === -1 || limit === '-1';
        const offset = isAll ? null : (Number(page) - 1) * Number(limit);

        const where: any = {};
        const finalIsOpportunity = isOpportunity !== undefined ? isOpportunity : isActive;
        
        if (search) where.name = { [Op.iLike]: `%${search}%` };
        if (stateId) where.stateId = stateId;
        if (zoneId) where.zoneId = zoneId;
        if (regionId) where.regionId = regionId;
        if (finalIsOpportunity !== undefined) where.isOpportunity = finalIsOpportunity === 'true';

        const { count, rows: districts } = await db.District.findAndCountAll({
            where,
            include: [
                { model: db.Zone, as: 'zone', attributes: ['id', 'name'] },
                { model: db.Region, as: 'region', attributes: ['id', 'name'] },
                { model: db.State, as: 'state', attributes: ['id', 'name'] },
                { model: db.User, as: 'asm', attributes: ['id', 'fullName', 'email', 'employeeId'] },
                { model: db.User, as: 'zonalManager', attributes: ['id', 'fullName', 'email', 'employeeId'] }
            ],
            order: [['name', 'ASC']],
            limit: isAll ? undefined : Number(limit),
            distinct: true
        });

        const result = districts.map((d: any) => ({
            ...d.toJSON(),
            zoneName: d.zone?.name || 'UNKNOWN',
            regionName: d.region?.name || 'UNKNOWN',
            stateName: d.state?.name || 'UNKNOWN',
            asmName: d.asm?.fullName || 'UNASSIGNED',
            zmName: d.zonalManager?.fullName || 'UNASSIGNED'
        }));

        res.json({ success: true, data: result, total: count });
    } catch (error) {
        console.error('Get districts error:', error);
        res.status(500).json({ success: false, message: 'Error fetching districts' });
    }
};

export const createDistrict = async (req: Request, res: Response) => {
    try {
        const { name, code, stateName, city, openFrom, openTo, status, isActive, isOpportunity, description, districtId } = req.body;
        const finalIsOpportunity = isOpportunity !== undefined ? isOpportunity : (isActive !== undefined ? isActive : true);

        // Preferred path: create location against an existing district
        if (districtId) {
            const district = await db.District.findByPk(districtId);
            if (!district) {
                return res.status(404).json({ success: false, message: 'District not found' });
            }

            const areaName = name || city || district.name;
            const area = await db.Location.create({
                name: areaName,
                districtId: district.id,
                city: city || areaName,
                isOpportunity: finalIsOpportunity,
                openFrom: openFrom || null,
                openTo: openTo || null,
                description: description || null
            });

            await db.Opportunity.create({
                districtId: district.id,
                areaId: area.id,
                city: city || areaName,
                openFrom: openFrom || null,
                openTo: openTo || null,
                status: status || 'inactive',
                opportunityType: 'New Dealership',
                capacity: 'Standard',
                priority: 'Medium'
            });

            return res.status(201).json({ success: true, data: area });
        }

        if (!name) return res.status(400).json({ success: false, message: 'District name is required' });
        
        // Find or Create state if stateName provided
        let stateId = req.body.stateId;
        if (stateName && !stateId) {
            const [state] = await db.State.findOrCreate({
                where: { name: stateName },
                defaults: { name: stateName }
            });
            stateId = state.id;
        }

        const district = await db.District.create({
            name,
            code,
            stateId,
            isOpportunity: finalIsOpportunity
        });

        const area = await db.Location.create({
            name,
            districtId: district.id,
            city: city || name,
            isOpportunity: true,
            openFrom: openFrom || null,
            openTo: openTo || null,
            description: description || null
        });

        // Create associated Opportunity for "Active Period" and "City"
        await db.Opportunity.create({
            districtId: district.id,
            areaId: area.id,
            city: city || name,
            openFrom: openFrom || null,
            openTo: openTo || null,
            status: status || 'inactive',
            opportunityType: 'New Dealership',
            capacity: 'Standard',
            priority: 'Medium'
        });

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.MASTER_HIERARCHY,
            entityType: 'district',
            entityId: district.id,
            entityLabel: `District ${district.name}${district.code ? ` (${district.code})` : ''}`,
            action: SYSTEM_AUDIT_ACTIONS.CREATED,
            description: `Created district ${district.name}${city ? ` · area ${city}` : ''}`,
            newData: {
                districtId: district.id,
                districtName: district.name,
                areaId: area.id,
                city: city || name,
                isOpportunity: finalIsOpportunity
            }
        });

        res.status(201).json({ success: true, data: area });
    } catch (error) {
        console.error('Create area error:', error);
        res.status(500).json({ success: false, message: 'Error creating area' });
    }
};

// --- Regions ---
export const getRegions = async (req: Request, res: Response) => {
    try {
        const regions = await db.Region.findAll({
            include: [
                { model: db.Zone, as: 'zone', attributes: ['name'] },
                { 
                    model: db.District, 
                    as: 'districts', 
                    attributes: ['id', 'name', 'stateId'],
                    include: [{ model: db.State, as: 'state', attributes: ['id', 'name'] }]
                }
            ],
            order: [['name', 'ASC']]
        });

        const roles = await db.Role.findAll({
            where: { 
                roleCode: { [db.Sequelize.Op.in]: ['ASM', 'RM', 'RBM'] }
            }
        });
        const asmRoleIds = roles.filter((r: any) => r.roleCode === 'ASM').map((r: any) => r.id);
        const rmRoleIds = roles.filter((r: any) => ['RM', 'RBM'].includes(r.roleCode)).map((r: any) => r.id);

        const result = await Promise.all(regions.map(async (region: any) => {
            const regionJson = region.toJSON();
            regionJson.zoneName = region.zone?.name || 'UNKNOWN';

            const districtIds = (region.districts || []).map((d: any) => d.id);

            const [asmCount, rmCount, rmAssignment] = await Promise.all([
                db.UserRole.count({ where: { roleId: { [db.Sequelize.Op.in]: asmRoleIds }, districtId: { [db.Sequelize.Op.in]: districtIds }, isActive: true }, distinct: true, col: 'userId' }),
                db.UserRole.count({ where: { roleId: { [db.Sequelize.Op.in]: rmRoleIds }, regionId: region.id, isActive: true }, distinct: true, col: 'userId' }),
                db.UserRole.findOne({
                    where: { roleId: { [db.Sequelize.Op.in]: rmRoleIds }, regionId: region.id, isActive: true },
                    include: [{ model: db.User, as: 'user', attributes: ['id', 'fullName', 'email', 'mobileNumber', 'employeeId'] }]
                })
            ]);

            regionJson.asmCount = asmCount;
            regionJson.regionalOfficerCount = rmCount;
            regionJson.regionalManager = rmAssignment?.user || null;
            regionJson.rbmCode = region.rbmCode || 'N/A';
            
            // Extract unique states for this region
            const statesMap = new Map();
            (region.districts || []).forEach((d: any) => {
                if (d.state) {
                    statesMap.set(d.state.id, d.state.name);
                }
            });
            regionJson.states = Array.from(statesMap.values());
            
            regionJson.districts = (region.districts || []).map((d: any) => ({ 
                id: d.id, 
                name: d.name.toUpperCase(),
                stateId: d.stateId
            }));
            return regionJson;
        }));

        res.json({ success: true, data: result });
    } catch (error) {
        console.error('Get regions error:', error);
        res.status(500).json({ success: false, message: 'Error fetching regions' });
    }
};

export const createRegion = async (req: Request, res: Response) => {
    try {
        const { name, parentId, zoneId, managerId, districts, districtIds } = req.body;
        const targetZoneId = zoneId || parentId;
        if (!name) return res.status(400).json({ success: false, message: 'Region name is required' });
        if (!targetZoneId) return res.status(400).json({ success: false, message: 'Zone is required for region creation' });

        const generatedCode = await nextRegionCode(targetZoneId);
        const region = await db.Region.create({ name, code: generatedCode, zoneId: targetZoneId });
        
        // 1. Assign Manager (RBM is the regional manager role; keep RM as legacy fallback)
        if (managerId) {
            const rmRole = await db.Role.findOne({
                where: {
                    roleCode: { [db.Sequelize.Op.in]: [ROLES.RBM, 'RM'] }
                }
            });
            if (rmRole) {
                await db.UserRole.update({ isActive: false }, { where: { regionId: region.id, roleId: rmRole.id } });
                const managerCode = await resolveManagerCode(rmRole.id, rmRole.roleCode, null);
                await db.UserRole.create({
                    userId: managerId,
                    roleId: rmRole.id,
                    regionId: region.id,
                    zoneId: targetZoneId,
                    managerCode,
                    isActive: true,
                    isPrimary: true
                });
            }
        }

        // 2. Assign Districts (with conflict check)
        const targetDistrictIds = districts || districtIds;
        if (Array.isArray(targetDistrictIds) && targetDistrictIds.length > 0) {
            const conflicts = await db.District.findAll({
                where: {
                    id: { [db.Sequelize.Op.in]: targetDistrictIds },
                    regionId: { [db.Sequelize.Op.and]: [{ [db.Sequelize.Op.ne]: null }, { [db.Sequelize.Op.ne]: region.id }] }
                }
            });
            if (conflicts.length > 0) {
                return res.status(409).json({
                    success: false,
                    message: `Districts already assigned to another region: ${conflicts.map((c: any) => c.name).join(', ')}`
                });
            }
            await db.District.update(
                { regionId: region.id, zoneId: targetZoneId }, 
                { where: { id: { [db.Sequelize.Op.in]: targetDistrictIds } } }
            );
        }
        
        await syncRegionManager(region.id);
        if (Array.isArray(targetDistrictIds) && targetDistrictIds.length > 0) {
            await syncDistrictsByRegion(region.id);
        }

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.MASTER_HIERARCHY,
            entityType: 'region',
            entityId: region.id,
            entityLabel: `Region ${region.name} (${generatedCode})`,
            action: SYSTEM_AUDIT_ACTIONS.CREATED,
            description: `Created region ${region.name} under zone ${targetZoneId}${
                Array.isArray(targetDistrictIds) && targetDistrictIds.length > 0
                    ? `; assigned ${targetDistrictIds.length} district(s)`
                    : ''
            }`,
            newData: {
                regionId: region.id,
                regionName: region.name,
                regionCode: generatedCode,
                zoneId: targetZoneId,
                managerId: managerId || null,
                districtIds: targetDistrictIds || []
            }
        });

        res.status(201).json({ success: true, message: 'Region created', data: region });
    } catch (error: any) {
        console.error('Create region error:', error);
        if (error.name === 'SequelizeUniqueConstraintError') {
            const field = error.errors?.[0]?.path || 'field';
            const value = error.errors?.[0]?.value || '';
            return res.status(409).json({ 
                success: false, 
                message: `A region with this ${field} "${value}" already exists. Please use a different name.` 
            });
        }
        res.status(500).json({ success: false, message: 'Error creating region' });
    }
};

export const updateRegion = async (req: Request, res: Response) => {
    try {
        const { id } = req.params;
        const { name, parentId, zoneId, managerId, districts, districtIds } = req.body;
        const targetZoneId = zoneId || parentId;
        
        const region = await db.Region.findByPk(id);
        if (!region) return res.status(404).json({ success: false, message: 'Region not found' });

        const previousRegionSnapshot = {
            name: region.name,
            code: region.code,
            zoneId: region.zoneId
        };

        const nextZoneId = targetZoneId || region.zoneId;
        const zoneChanged = Boolean(targetZoneId && targetZoneId !== region.zoneId);
        const generatedCode =
            zoneChanged || !region.code
                ? await nextRegionCode(nextZoneId, id as string)
                : region.code;

        await region.update({
            name,
            code: generatedCode,
            zoneId: nextZoneId
        });
        
        // 1. Update Manager (RBM is the regional manager role; keep RM as legacy fallback)
        if (managerId) {
            const rmRole = await db.Role.findOne({
                where: {
                    roleCode: { [db.Sequelize.Op.in]: [ROLES.RBM, 'RM'] }
                }
            });
            if (rmRole) {
                // Deactivate old RMs for this region
                await db.UserRole.update({ isActive: false }, { 
                    where: { regionId: id, roleId: rmRole.id } 
                });
                // Assign new RM
                const managerCode = await resolveManagerCode(rmRole.id, rmRole.roleCode, null);
                await db.UserRole.create({
                    userId: managerId,
                    roleId: rmRole.id,
                    regionId: id,
                    zoneId: region.zoneId,
                    managerCode,
                    isActive: true,
                    isPrimary: true
                });
            }
        }

        // 2. Update Districts (with conflict check)
        const targetDistrictIds = districts || districtIds;
        if (Array.isArray(targetDistrictIds)) {
            if (targetDistrictIds.length > 0) {
                const conflicts = await db.District.findAll({
                    where: {
                        id: { [db.Sequelize.Op.in]: targetDistrictIds },
                        regionId: { [db.Sequelize.Op.and]: [{ [db.Sequelize.Op.ne]: null }, { [db.Sequelize.Op.ne]: id }] }
                    }
                });
                if (conflicts.length > 0) {
                    return res.status(409).json({
                        success: false,
                        message: `Districts already assigned to another region: ${conflicts.map((c: any) => c.name).join(', ')}`
                    });
                }
            }
            await db.District.update({ regionId: null }, { where: { regionId: id } });
            if (targetDistrictIds.length > 0) {
                await db.District.update(
                    { regionId: id, zoneId: region.zoneId }, 
                    { where: { id: { [db.Sequelize.Op.in]: targetDistrictIds } } }
                );
            }
        }
        
        await syncRegionManager(id as string);
        await syncDistrictsByRegion(id as string);

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.MASTER_HIERARCHY,
            entityType: 'region',
            entityId: id as string,
            entityLabel: `Region ${name || region.name} (${generatedCode})`,
            action: SYSTEM_AUDIT_ACTIONS.UPDATED,
            description: `Updated region ${name || region.name}${
                zoneChanged ? ` (moved to zone ${nextZoneId})` : ''
            }${managerId ? ` · manager set to ${managerId}` : ''}`,
            oldData: previousRegionSnapshot,
            newData: {
                name,
                code: generatedCode,
                zoneId: nextZoneId,
                managerId: managerId || null,
                districtIds: targetDistrictIds || null
            }
        });

        res.json({ success: true, message: 'Region updated' });
    } catch (error: any) {
        console.error('Update region error:', error);
        if (error.name === 'SequelizeUniqueConstraintError') {
            const field = error.errors?.[0]?.path || 'field';
            const value = error.errors?.[0]?.value || '';
            return res.status(409).json({ 
                success: false, 
                message: `A region with this ${field} "${value}" already exists. Please use a different name.`
            });
        }
        res.status(500).json({ success: false, message: 'Error updating region' });
    }
};

// --- Zones ---
export const getZones = async (req: Request, res: Response) => {
    try {
        const zones = await db.Zone.findAll({
            include: [
                { model: db.Region, as: 'regions', attributes: ['id', 'name'] },
                { model: db.State, as: 'states', attributes: ['id', 'name'] },
                { model: db.District, as: 'districts', attributes: ['id'] },
                { model: db.User, as: 'zonalBusinessHead', attributes: ['id', 'fullName', 'email', 'employeeId'] }
            ],
            order: [['name', 'ASC']]
        });

        const roles = await db.Role.findAll({
            where: { roleCode: { [db.Sequelize.Op.in]: ['ZBH', 'DD-ZM'] } }
        });
        const zbhRoleIds = roles.filter((r: any) => r.roleCode === 'ZBH').map((r: any) => r.id);
        const zmRoleIds = roles.filter((r: any) => r.roleCode === 'DD-ZM').map((r: any) => r.id);

        const result = await Promise.all(zones.map(async (zone: any) => {
            const zoneJson = zone.toJSON();
            
            const [zbhAssignment, zms] = await Promise.all([
                db.UserRole.findOne({
                    where: { roleId: { [db.Sequelize.Op.in]: zbhRoleIds }, zoneId: zone.id, isActive: true },
                    include: [{ model: db.User, as: 'user', attributes: ['id', 'fullName', 'email', 'mobileNumber', 'employeeId'] }],
                    order: [['assignedAt', 'DESC']]
                }),
                db.UserRole.findAll({
                    where: { roleId: { [db.Sequelize.Op.in]: zmRoleIds }, zoneId: zone.id, isActive: true },
                    include: [{ model: db.User, as: 'user', attributes: ['id', 'fullName', 'email', 'mobileNumber', 'employeeId'] }]
                })
            ]);
            
            // For each ZM, fetch their assigned regions in this zone
            const zonalManagers = await Promise.all(zms.map(async (zmRole: any) => {
                // Fetch all active regions assigned to this ZM in this zone
                const assignedRoles = await db.UserRole.findAll({
                    where: { 
                        userId: zmRole.user.id, 
                        zoneId: zone.id, 
                        isActive: true,
                        roleId: { [db.Sequelize.Op.in]: zmRoleIds }
                    },
                    include: [{ model: db.Region, as: 'region', attributes: ['id', 'name'] }]
                });

                const regionNames = Array.from(new Set(
                    assignedRoles
                        .filter((r: any) => r.region?.name)
                        .map((r: any) => r.region.name)
                ));

                return {
                    id: zmRole.user.id,
                    name: zmRole.user.fullName || zmRole.user.name,
                    email: zmRole.user.email,
                    phone: zmRole.user.mobileNumber || 'N/A',
                    code: zmRole.managerCode || zmRole.user.employeeId || 'N/A',
                    regions: regionNames
                };
            }));
            
            zoneJson.regionCount = (zone.regions || []).length;
            zoneJson.districtCount = (zone.districts || []).length;
            zoneJson.states = (zone.states || []).map((s: any) => s.name.toUpperCase());
            zoneJson.zmCount = zms.length;
            zoneJson.zonalBusinessHead = zbhAssignment ? {
                id: zbhAssignment.user.id,
                name: zbhAssignment.user.fullName,
                email: zbhAssignment.user.email,
                phone: zbhAssignment.user.mobileNumber || 'N/A',
                code: zone.zbhCode || 'N/A'
            } : (zone.zonalBusinessHead ? {
                id: zone.zonalBusinessHead.id,
                name: zone.zonalBusinessHead.fullName,
                email: zone.zonalBusinessHead.email,
                phone: zone.zonalBusinessHead.mobileNumber || 'N/A',
                code: zone.zbhCode || 'N/A'
            } : null);
            zoneJson.zonalManagers = zonalManagers;
            return zoneJson;
        }));
        res.json({ success: true, data: result });
    } catch (error) {
        console.error('Get zones error:', error);
        res.status(500).json({ success: false, message: 'Error fetching zones' });
    }
};

export const createZone = async (req: Request, res: Response) => {
    try {
        const { name, code, stateIds, managerId } = req.body;
        if (!name) return res.status(400).json({ success: false, message: 'Zone name is required' });
        
        const zone = await db.Zone.create({ name, code });
        
        if (managerId && managerId !== 'none') {
            const zbhRole = await db.Role.findOne({ 
                where: { 
                    [db.Sequelize.Op.or]: [
                        { roleCode: ROLES.ZBH },
                        { roleName: { [db.Sequelize.Op.iLike]: '%Zonal Business Head%' } },
                        { roleName: { [db.Sequelize.Op.iLike]: '%Zone Business Head%' } }
                    ]
                } 
            });

            if (zbhRole) {
                // Deactivate any existing active ZBH roles for this zone (unlikely for new zone but safe)
                await db.UserRole.update({ isActive: false }, { where: { zoneId: zone.id, roleId: zbhRole.id, isActive: true } });
                
                await db.UserRole.create({
                    userId: managerId,
                    roleId: zbhRole.id,
                    zoneId: zone.id,
                    isActive: true,
                    isPrimary: true
                });

                // Sync to Zone model
                const { syncZoneManager } = await import('./syncHierarchy.service.js');
                await syncZoneManager(zone.id as string);
            }
        }

        if (Array.isArray(stateIds) && stateIds.length > 0) {
            await db.State.update({ zoneId: zone.id }, { where: { id: { [db.Sequelize.Op.in]: stateIds } } });
            await db.District.update({ zoneId: zone.id }, { where: { stateId: { [db.Sequelize.Op.in]: stateIds } } });
        }

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.MASTER_HIERARCHY,
            entityType: 'zone',
            entityId: zone.id,
            entityLabel: `Zone ${name}${code ? ` (${code})` : ''}`,
            action: SYSTEM_AUDIT_ACTIONS.CREATED,
            description: `Created zone ${name}${managerId && managerId !== 'none' ? ` · ZBH ${managerId}` : ''}${
                Array.isArray(stateIds) && stateIds.length > 0 ? ` · linked ${stateIds.length} state(s)` : ''
            }`,
            newData: {
                zoneId: zone.id,
                name,
                code,
                managerId: managerId && managerId !== 'none' ? managerId : null,
                stateIds: stateIds || []
            }
        });

        res.status(201).json({ success: true, message: 'Zone created', data: zone });
    } catch (error) {
        console.error('Create zone error:', error);
        res.status(500).json({ success: false, message: 'Error creating zone' });
    }
};

export const updateZone = async (req: Request, res: Response) => {
    try {
        const { id } = req.params;
        const { name, code, stateIds, managerId } = req.body;
        const zone = await db.Zone.findByPk(id);
        if (!zone) return res.status(404).json({ success: false, message: 'Zone not found' });

        const previousZoneSnapshot = { name: zone.name, code: zone.code };

        await zone.update({ name, code });
        
        const { syncZoneManager } = await import('./syncHierarchy.service.js');

        if (managerId && managerId !== 'none') {
            const zbhRole = await db.Role.findOne({ 
                where: { 
                    [db.Sequelize.Op.or]: [
                        { roleCode: ROLES.ZBH },
                        { roleName: { [db.Sequelize.Op.iLike]: '%Zonal Business Head%' } },
                        { roleName: { [db.Sequelize.Op.iLike]: '%Zone Business Head%' } }
                    ]
                } 
            });

            if (zbhRole) {
                // 1. Deactivate old ZBHs for this zone
                await db.UserRole.update({ isActive: false }, { 
                    where: { zoneId: id, roleId: zbhRole.id, isActive: true } 
                });

                // 2. Assign new ZBH role
                await db.UserRole.create({
                    userId: managerId,
                    roleId: zbhRole.id,
                    zoneId: id,
                    isActive: true,
                    isPrimary: true
                });

                // 3. Sync to Zone model
                await syncZoneManager(id as string);
            }
        } else if (managerId === null || managerId === 'none') {
            // Find ZBH role to deactivate
            const zbhRole = await db.Role.findOne({ 
                where: { 
                    [db.Sequelize.Op.or]: [
                        { roleCode: ROLES.ZBH },
                        { roleName: { [db.Sequelize.Op.iLike]: '%Zonal Business Head%' } },
                        { roleName: { [db.Sequelize.Op.iLike]: '%Zone Business Head%' } }
                    ]
                } 
            });
            
            if (zbhRole) {
                await db.UserRole.update({ isActive: false }, { 
                    where: { zoneId: id, roleId: zbhRole.id, isActive: true } 
                });
            }

            // Sync to Zone model (will set zbhId to null)
            await syncZoneManager(id as string);
        }

        if (Array.isArray(stateIds)) {
            await db.State.update({ zoneId: null }, { where: { zoneId: id } });
            await db.District.update({ zoneId: null }, { where: { zoneId: id } });
            
            if (stateIds.length > 0) {
                await db.State.update({ zoneId: id }, { where: { id: { [db.Sequelize.Op.in]: stateIds } } });
                await db.District.update({ zoneId: id }, { where: { stateId: { [db.Sequelize.Op.in]: stateIds } } });
            }
        }

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.MASTER_HIERARCHY,
            entityType: 'zone',
            entityId: id as string,
            entityLabel: `Zone ${name || zone.name}${code ? ` (${code})` : ''}`,
            action: SYSTEM_AUDIT_ACTIONS.UPDATED,
            description: `Updated zone ${name || zone.name}${
                managerId && managerId !== 'none' ? ` · ZBH set to ${managerId}` : ''
            }${managerId === null || managerId === 'none' ? ' · ZBH cleared' : ''}`,
            oldData: previousZoneSnapshot,
            newData: {
                name,
                code,
                managerId: managerId === 'none' ? null : managerId ?? undefined,
                stateIds: Array.isArray(stateIds) ? stateIds : undefined
            }
        });

        res.json({ success: true, message: 'Zone updated' });
    } catch (error) {
        console.error('Update zone error:', error);
        res.status(500).json({ success: false, message: 'Error updating zone' });
    }
};

// --- States ---
export const getStates = async (req: Request, res: Response) => {
    try {
        const states = await db.State.findAll({
            include: [{ model: db.Zone, as: 'zone', attributes: ['name'] }],
            order: [['name', 'ASC']]
        });
        res.json({ success: true, data: states });
    } catch (error) {
        console.error('Get states error:', error);
        res.status(500).json({ success: false, message: 'Error fetching states' });
    }
};

export const createState = async (req: Request, res: Response) => {
    try {
        const { name, zoneId } = req.body;
        if (!name) return res.status(400).json({ success: false, message: 'State name is required' });
        
        const state = await db.State.create({ name, zoneId });
        if (zoneId) {
            await db.District.update({ zoneId }, { where: { stateId: state.id } });
        }

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.MASTER_HIERARCHY,
            entityType: 'state',
            entityId: state.id,
            entityLabel: `State ${name}`,
            action: SYSTEM_AUDIT_ACTIONS.CREATED,
            description: `Created state ${name}${zoneId ? ` under zone ${zoneId}` : ''}`,
            newData: { stateId: state.id, name, zoneId: zoneId || null }
        });

        res.status(201).json({ success: true, data: state });
    } catch (error) {
        console.error('Create state error:', error);
        res.status(500).json({ success: false, message: 'Error creating state' });
    }
};

// --- Managers ---
export const getManagersByRole = async (req: Request, res: Response) => {
    try {
        const { roleCode, locationId } = req.query as any;
        const managers = await User.findAll({
            attributes: ['id', 'fullName', 'email', 'mobileNumber', 'roleCode'],
            include: [
                { 
                    model: db.UserRole, 
                    as: 'userRoles', 
                    include: [{ model: db.Role, as: 'role' }] 
                }
            ]
        });
        const filteredManagers = managers.filter((m: any) => {
            const hasRole = !roleCode || m.roleCode === roleCode || (m.userRoles || []).some((a: any) => a.role?.roleCode === roleCode);
            const hasLocation = !locationId || (m.userRoles || []).some((a: any) => 
                a.districtId === locationId || 
                a.zoneId === locationId || 
                a.regionId === locationId
            );
            return hasRole && hasLocation;
        });
        res.json({ success: true, data: filteredManagers });
    } catch (error) {
        console.error('Get managers error:', error);
        res.status(500).json({ success: false, message: 'Error fetching managers' });
    }
};

export const getAreaManagers = async (req: Request, res: Response) => {
    req.query.roleCode = 'ASM';
    return getManagersByRole(req, res);
};

// --- Delete Area (Location) ---
export const deleteLocation = async (req: Request, res: Response) => {
    try {
        const { id } = req.params;
        const area = await db.Location.findByPk(id);
        if (!area) return res.status(404).json({ success: false, message: 'Area not found' });

        const snapshot = {
            id: area.id,
            name: area.name,
            districtId: area.districtId,
            city: area.city
        };

        // Delete associated opportunities if they belong to this granular location
        await db.Opportunity.destroy({ where: { areaId: id } });
        
        // Delete the location itself
        await area.destroy();

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.MASTER_HIERARCHY,
            entityType: 'area',
            entityId: id as string,
            entityLabel: `Area ${snapshot.name}`,
            action: SYSTEM_AUDIT_ACTIONS.DELETED,
            description: `Deleted area ${snapshot.name} and any linked opportunities`,
            oldData: snapshot
        });

        res.json({ success: true, message: 'Area deleted successfully' });
    } catch (error) {
        console.error('Delete area error:', error);
        res.status(500).json({ success: false, message: 'Error deleting area' });
    }
};

export const updateLocation = async (req: Request, res: Response) => {
    try {
        const { id } = req.params; // This is the Area ID
        const { name, code, stateName, city, openFrom, openTo, status, isActive, isOpportunity, description, districtId } = req.body;
        const finalIsOpportunity = isOpportunity !== undefined ? isOpportunity : isActive;
        
        const area = await db.Location.findByPk(id, {
            include: [{ model: db.District, as: 'district' }]
        });
        if (!area) return res.status(404).json({ success: false, message: 'Area not found' });

        const previousAreaSnapshot = {
            name: area.name,
            districtId: area.districtId,
            city: area.city,
            isOpportunity: area.isOpportunity,
            openFrom: area.openFrom,
            openTo: area.openTo
        };

        let district = area.district;

        if (districtId && (!district || String(district.id) !== String(districtId))) {
            const nextDistrict = await db.District.findByPk(districtId);
            if (!nextDistrict) {
                return res.status(404).json({ success: false, message: 'District not found' });
            }
            district = nextDistrict;
        }
        
        // 1. Update District
        if (district && !districtId) {
            let stateId = req.body.stateId;
            if (stateName && !stateId) {
                const [state] = await db.State.findOrCreate({
                    where: { name: stateName },
                    defaults: { name: stateName }
                });
                stateId = state.id;
            }

            await district.update({
                name: name || district.name,
                code: code || district.code,
                stateId: stateId || district.stateId,
                isOpportunity: finalIsOpportunity !== undefined ? finalIsOpportunity : district.isOpportunity
            });
        }

        // 2. Update Area
        await area.update({
            name: name || area.name,
            districtId: district?.id || area.districtId,
            city: city || area.city,
            isOpportunity: finalIsOpportunity !== undefined ? finalIsOpportunity : area.isOpportunity,
            openFrom: openFrom || area.openFrom,
            openTo: openTo || area.openTo,
            description: description || area.description
        });

        // 3. Update or Create associated Opportunity
        const [opportunity] = await db.Opportunity.findOrBuild({
            where: { areaId: id }
        });

        opportunity.set({
            districtId: district?.id || opportunity.districtId,
            city: city || opportunity.city || name || area.name,
            openFrom: openFrom !== undefined ? (openFrom || null) : opportunity.openFrom,
            openTo: openTo !== undefined ? (openTo || null) : opportunity.openTo,
            status: status || opportunity.status || 'inactive'
        });
        await opportunity.save();

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.MASTER_HIERARCHY,
            entityType: 'area',
            entityId: id as string,
            entityLabel: `Area ${name || area.name}`,
            action: SYSTEM_AUDIT_ACTIONS.UPDATED,
            description: `Updated area ${name || area.name}`,
            oldData: previousAreaSnapshot,
            newData: {
                name: name || area.name,
                districtId: district?.id || area.districtId,
                city: city || area.city,
                isOpportunity: finalIsOpportunity,
                openFrom,
                openTo,
                status
            }
        });

        res.json({ success: true, message: 'Area updated' });
        
        if (district && typeof district.id === 'string') {
            await syncLocationManagers(district.id);
        }
    } catch (error) {
        console.error('Update area error:', error);
        res.status(500).json({ success: false, message: 'Error updating area' });
    }
};

// --- Managers ---
export const getASMs = async (req: Request, res: Response) => {
    try {
        const asms = await User.findAll({
            where: { 
                roleCode: { [db.Sequelize.Op.in]: ['DD-AM', ROLES.DD_AM] },
                isActive: true 
            },
            include: [
                {
                    association: 'userRoles',
                    where: { isActive: true },
                    required: false,
                    include: [{ association: 'role', where: { roleCode: { [db.Sequelize.Op.in]: ['DD-AM', ROLES.DD_AM] } } }]
                },
                {
                    association: 'managedAreaDistricts',
                    include: [
                        { association: 'state', attributes: ['id', 'name'] },
                        { association: 'region', attributes: ['id', 'name'] },
                        { association: 'zone', attributes: ['id', 'name'] }
                    ]
                }
            ],
            order: [['fullName', 'ASC']]
        });

        const result = (asms || []).map((u: any) => {
            const ddAmDistricts = u.managedAreaDistricts || [];
            const districts = [...ddAmDistricts];
            
            const roleAssignment = (u.userRoles || []).find((r: any) => 
                ['DD-AM', ROLES.DD_AM].includes(r.role?.roleCode)
            );
            const managerCode = roleAssignment?.managerCode || u.employeeId;

            const zoneSet = new Set();
            const regionSet = new Set();
            const stateSet = new Set();
            
            const territoryInfo = districts.map((d: any) => {
                if (d.zone) zoneSet.add(JSON.stringify({ id: d.zone.id, name: d.zone.name }));
                if (d.region) regionSet.add(JSON.stringify({ id: d.region.id, name: d.region.name }));
                if (d.state) stateSet.add(d.state.name);
                
                return {
                    id: d.id,
                    name: d.name,
                    stateId: d.stateId,
                    regionId: d.regionId,
                    zoneId: d.zoneId
                };
            });

            const zones = Array.from(zoneSet).map((s: any) => JSON.parse(s));
            const regions = Array.from(regionSet).map((s: any) => JSON.parse(s));

            return {
                id: u.id,
                name: u.fullName,
                email: u.email,
                phone: u.mobileNumber,
                employeeId: u.employeeId,
                asmCode: managerCode || 'N/A', 
                roleCode: u.roleCode,
                status: u.status,
                zoneId: zones[0]?.id || '',
                zoneName: zones[0]?.name || 'Unassigned',
                regionId: regions[0]?.id || '',
                regionName: regions[0]?.name || 'Unassigned',
                areasManaged: territoryInfo,
                stateNames: Array.from(stateSet),
                totalDistricts: territoryInfo.length
            };
        });

        res.json({ success: true, data: result });
    } catch (error) {
        console.error('Get ASMs error:', error);
        res.status(500).json({ success: false, message: 'Error fetching ASMs' });
    }
};

export const getZonalManagers = async (req: Request, res: Response) => {
    try {
        const zms = await db.User.findAll({
            attributes: ['id', 'fullName', 'email', 'employeeId', 'status'],
            include: [
                {
                    model: db.UserRole,
                    as: 'userRoles',
                    where: { isActive: true },
                    required: true,
                    include: [
                        { 
                            model: db.Role, 
                            as: 'role', 
                            where: { roleCode: { [db.Sequelize.Op.in]: ['ZM', 'DD-ZM'] } } 
                        },
                        {
                            model: db.Region,
                            as: 'region',
                            attributes: ['id', 'name']
                        },
                        {
                            model: db.Zone,
                            as: 'zone',
                            attributes: ['id', 'name']
                        }
                    ]
                }
            ],
            order: [['fullName', 'ASC']]
        });

        const result = (zms || []).map((u: any) => {
            const rolePriority = ['DD-ZM', 'ZM'];
            const roleAssignments = (u.userRoles || []).filter((r: any) => rolePriority.includes(r.role?.roleCode));
            
            const mainAssignment = [...roleAssignments].sort((a: any, b: any) => {
                const aIndex = rolePriority.indexOf(a.role?.roleCode || '');
                const bIndex = rolePriority.indexOf(b.role?.roleCode || '');
                if (aIndex !== bIndex) return aIndex - bIndex;
                if (a.managerCode && !b.managerCode) return -1;
                return 0;
            })[0];

            const zmCode = mainAssignment?.managerCode || u.employeeId || 'N/A';
            
            const regionIds = (u.userRoles || [])
                .filter((ur: any) => (ur.role?.roleCode === 'DD-ZM' || ur.role?.roleCode === 'ZM') && ur.regionId)
                .map((ur: any) => ur.regionId);
            
            const regionNames = (u.userRoles || [])
                .filter((ur: any) => (ur.role?.roleCode === 'DD-ZM' || ur.role?.roleCode === 'ZM') && ur.region?.name)
                .map((ur: any) => ur.region.name);

            const zoneId = mainAssignment?.zoneId || (u.userRoles?.[0]?.zoneId) || null;
            const zoneName = mainAssignment?.zone?.name || (u.userRoles?.[0]?.zone?.name) || 'Not Assigned';

            return {
                id: u.id,
                name: u.fullName,
                email: u.email,
                employeeId: u.employeeId,
                zmCode: zmCode,
                status: u.status,
                zoneId: zoneId,
                zoneName: zoneName,
                assignedRegionIds: regionIds,
                regionNames: Array.from(new Set(regionNames))
            };
        });

        res.json({ success: true, data: result });
    } catch (error) {
        console.error('Get ZMs error:', error);
        res.status(500).json({ success: false, message: 'Error fetching Zonal Managers' });
    }
};

export const saveZM = async (req: Request, res: Response) => {
    try {
        const { userId, zmCode, zoneId, regionIds, status } = req.body;
        if (!userId) return res.status(400).json({ success: false, message: 'userId is required' });

        const zmRole = await db.Role.findOne({ where: { roleCode: 'DD-ZM' } });
        if (!zmRole) return res.status(404).json({ success: false, message: 'ZM role (DD-ZM) not found' });

        if (status) {
            await db.User.update({ status }, { where: { id: userId } });
        }

        // Deactivate existing ZM role assignments for this user
        await db.UserRole.update({ isActive: false }, {
            where: { userId, roleId: zmRole.id }
        });

        // Create new role assignments for each region
        if (Array.isArray(regionIds) && regionIds.length > 0) {
            for (const regionId of regionIds) {
                // Ensure exclusivity: Deactivate ANY existing ZM role assigned to this region
                await db.UserRole.update({ isActive: false }, {
                    where: { 
                        regionId: regionId, 
                        roleId: zmRole.id,
                        isActive: true
                    }
                });

                await db.UserRole.create({
                    userId,
                    roleId: zmRole.id,
                    zoneId: zoneId || null,
                    regionId: regionId,
                    managerCode: await resolveManagerCode(zmRole.id, 'DD-ZM', null),
                    isActive: true,
                    isPrimary: true
                });
            }
        } else {
            // Case with no specific region but assigned to a zone
            await db.UserRole.create({
                userId,
                roleId: zmRole.id,
                zoneId: zoneId || null,
                regionId: null,
                managerCode: await resolveManagerCode(zmRole.id, 'DD-ZM', null),
                isActive: true,
                isPrimary: true
            });
        }

        // Cleanup: ZMs no longer manage districts directly
        await db.District.update({ zmId: null, zmCode: null }, { where: { zmId: userId } });

        // Trigger sync for all affected regions to update district.zmId
        if (Array.isArray(regionIds) && regionIds.length > 0) {
            for (const regionId of regionIds) {
                await syncDistrictsByRegion(regionId);
            }
        }

        const targetUser = await db.User.findByPk(userId, { attributes: ['fullName', 'email'] });
        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.ROLE_ASSIGNMENT,
            entityType: 'zonal_manager',
            entityId: userId,
            entityLabel: targetUser?.fullName ? `ZM · ${targetUser.fullName}` : `ZM · ${userId}`,
            action: SYSTEM_AUDIT_ACTIONS.ASSIGNED,
            description: `Assigned ${targetUser?.fullName || userId} as Zonal Manager${
                Array.isArray(regionIds) && regionIds.length > 0 ? ` over ${regionIds.length} region(s)` : zoneId ? ` for zone ${zoneId}` : ''
            }`,
            newData: {
                userId,
                userName: targetUser?.fullName,
                userEmail: targetUser?.email,
                zmCode,
                zoneId: zoneId || null,
                regionIds: regionIds || [],
                status
            }
        });

        res.json({ success: true, message: 'Zonal Manager saved successfully' });
    } catch (error) {
        console.error('Save ZM error:', error);
        res.status(500).json({ success: false, message: 'Error saving Zonal Manager' });
    }
};


export const getDDLeads = async (req: Request, res: Response) => {
    try {
        const ddLeads = await db.User.findAll({
            attributes: ['id', 'fullName', 'email', 'employeeId', 'status'],
            include: [
                {
                    model: db.UserRole,
                    as: 'userRoles',
                    include: [{ 
                        model: db.Role, 
                        as: 'role', 
                        where: { roleCode: 'DD Lead' }
                    }]
                }
            ],
            order: [['status', 'ASC'], ['fullName', 'ASC']]
        });

        const result = (ddLeads || []).map((u: any) => {
            const roleAssignment = (u.userRoles || []).find((r: any) => (r.role?.roleCode === 'DD Lead'));
            const leadCode = roleAssignment?.managerCode || u.employeeId || 'N/A';
            const isActive = roleAssignment?.isActive || false;
            
            return {
                id: u.id,
                name: u.fullName,
                email: u.email,
                employeeId: u.employeeId,
                leadCode: leadCode,
                status: u.status,
                isActiveLead: isActive
            };
        });

        res.json({ success: true, data: result });
    } catch (error) {
        console.error('Get DD Leads error:', error);
        res.status(500).json({ success: false, message: 'Error fetching DD Leads' });
    }
};

export const saveDDLead = async (req: Request, res: Response) => {
    try {
        const { userId, leadCode, status, isActive } = req.body;
        if (!userId) return res.status(400).json({ success: false, message: 'userId is required' });

        const leadRole = await db.Role.findOne({ where: { roleCode: 'DD Lead' } });
        if (!leadRole) return res.status(404).json({ success: false, message: 'DD Lead role not found' });

        if (status) {
            await db.User.update({ status }, { where: { id: userId } });
        }

        // --- SINGLETON VALIDATION ---
        // If we are trying to activate this user as DD Lead, check if another active lead exists
        if (isActive === true || isActive === 'true') {
            const existingActiveLead = await db.UserRole.findOne({
                where: {
                    roleId: leadRole.id,
                    isActive: true,
                    userId: { [db.Sequelize.Op.ne]: userId } // Exclude current user
                },
                include: [{ model: db.User, as: 'user' }]
            });

            if (existingActiveLead) {
                return res.status(409).json({
                    success: false,
                    message: `An active DD Lead already exists (${existingActiveLead.user?.fullName}). Please deactivate the current lead before assigning a new one.`
                });
            }
        }

        // Deactivate existing DD Lead roles for this user to start fresh (National approach)
        await db.UserRole.update({ isActive: false }, {
            where: { userId, roleId: leadRole.id }
        });

        const resolvedActive = isActive !== undefined ? (isActive === true || isActive === 'true') : true;

        // Create/Activate the single National DD Lead role assignment
        await db.UserRole.create({
            userId,
            roleId: leadRole.id,
            zoneId: null, // Global scope
            regionId: null, // Global scope
            districtId: null, // Global scope
            managerCode: await resolveManagerCode(leadRole.id, 'DD Lead', null),
            isActive: resolvedActive,
            isPrimary: true
        });

        const targetUser = await db.User.findByPk(userId, { attributes: ['fullName', 'email'] });
        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.ROLE_ASSIGNMENT,
            entityType: 'dd_lead',
            entityId: userId,
            entityLabel: targetUser?.fullName ? `DD Lead · ${targetUser.fullName}` : `DD Lead · ${userId}`,
            action: resolvedActive ? SYSTEM_AUDIT_ACTIONS.ASSIGNED : SYSTEM_AUDIT_ACTIONS.UNASSIGNED,
            description: `${
                resolvedActive ? 'Activated' : 'Deactivated'
            } national DD Lead role for ${targetUser?.fullName || userId}`,
            newData: { userId, leadCode, status, isActive: resolvedActive }
        });

        res.json({ success: true, message: 'DD Lead updated successfully' });
    } catch (error) {
        console.error('Save DD Lead error:', error);
        res.status(500).json({ success: false, message: 'Error saving DD Lead' });
    }
};


export const createArea = createDistrict;
export const deleteArea = deleteLocation;
export const createDistrictLegacy = createDistrict;


// --- System Configuration ---
export const getSystemConfigs = async (req: Request, res: Response) => {
    try {
        const { category, key } = req.query;
        const where: any = { isActive: true };
        
        if (category) where.category = category;
        if (key) where.key = key;

        const configs = await db.SystemConfiguration.findAll({ where });
        
        // Transform into a key-value map for easier frontend consumption if requested
        if (req.query.format === 'map') {
            const configMap: any = {};
            configs.forEach((c: any) => {
                configMap[c.key] = c.value;
            });
            return res.json({ success: true, data: configMap });
        }

        res.json({ success: true, data: configs });
    } catch (error) {
        console.error('Get system configs error:', error);
        res.status(500).json({ success: false, message: 'Error fetching system configurations' });
    }
};

export const saveSystemConfig = async (req: Request, res: Response) => {
    try {
        const { id, key, value, category, description, isActive } = req.body;
        
        let config;
        let previousSnapshot: Record<string, unknown> | null = null;
        
        // Use key as the unique identifier if id isn't present
        if (id) {
            config = await db.SystemConfiguration.findByPk(id);
        } else if (key) {
            config = await db.SystemConfiguration.findOne({ where: { key } });
        }

        const isUpdate = Boolean(config);
        if (config) {
            previousSnapshot = {
                key: config.key,
                value: config.value,
                category: config.category,
                description: config.description,
                isActive: config.isActive
            };
            await config.update({ key, value, category, description, isActive });
        } else {
            config = await db.SystemConfiguration.create({ 
                key, 
                value, 
                category, 
                description, 
                isActive: isActive !== undefined ? isActive : true 
            });
        }

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.SYSTEM_CONFIG,
            entityType: 'system_configuration',
            entityId: config.id,
            entityLabel: `${category ? `${category} · ` : ''}${key}`,
            action: isUpdate ? SYSTEM_AUDIT_ACTIONS.UPDATED : SYSTEM_AUDIT_ACTIONS.CREATED,
            description: `${isUpdate ? 'Updated' : 'Created'} system config ${key}${category ? ` (${category})` : ''}`,
            oldData: previousSnapshot,
            newData: { key, value, category, description, isActive }
        });

        res.json({ success: true, data: config });
    } catch (error) {
        console.error('Save system config error:', error);
        res.status(500).json({ success: false, message: 'Error saving system configuration' });
    }
};

export const getDealerAsmMappings = async (req: Request, res: Response) => {
    try {
        const [dealers, asms] = await Promise.all([
            db.Dealer.findAll({
                include: [
                    { model: db.DealerCode, as: 'dealerCode', attributes: ['dealerCode', 'salesCode'] },
                    { model: db.User, as: 'user', attributes: ['id', 'fullName', 'email', 'status', 'isActive'] },
                    { model: db.User, as: 'asmManager', attributes: ['id', 'fullName', 'email', 'employeeId'], required: false }
                ],
                order: [['createdAt', 'DESC']]
            }),
            db.User.findAll({
                where: {
                    roleCode: { [Op.in]: ['ASM', 'AREA SALES MANAGER'] },
                    isActive: true
                },
                attributes: ['id', 'fullName', 'email', 'employeeId', 'roleCode']
            })
        ]);

        const rows = (dealers || []).map((d: any) => {
            return {
                dealerId: d.id,
                dealerName: d.businessName || d.legalName || 'Dealer',
                legalName: d.legalName,
                dealerCode: d.dealerCode?.dealerCode || d.dealerCode?.salesCode || '',
                status: d.status,
                onboardedAt: d.onboardedAt,
                dealerUser: d.user ? {
                    id: d.user.id,
                    fullName: d.user.fullName,
                    email: d.user.email
                } : null,
                assignedAsm: d.asmManager ? {
                    id: d.asmManager.id,
                    fullName: d.asmManager.fullName,
                    email: d.asmManager.email,
                    employeeId: d.asmManager.employeeId
                } : null,
                assignedAt: null,
                assignedBy: null
            };
        });

        res.json({
            success: true,
            data: {
                dealers: rows,
                asmUsers: asms
            }
        });
    } catch (error) {
        console.error('Get dealer ASM mappings error:', error);
        res.status(500).json({ success: false, message: 'Error fetching dealer ASM mappings' });
    }
};

export const saveDealerAsmMapping = async (req: Request, res: Response) => {
    try {
        const { dealerId, asmUserId } = req.body;
        if (!dealerId) {
            return res.status(400).json({ success: false, message: 'dealerId is required' });
        }

        const dealer = await db.Dealer.findByPk(dealerId);
        if (!dealer) {
            return res.status(404).json({ success: false, message: 'Dealer not found' });
        }

        let asmUser: any = null;
        if (asmUserId) {
            asmUser = await db.User.findOne({
                where: {
                    id: asmUserId,
                    roleCode: { [Op.in]: ['ASM', 'AREA SALES MANAGER'] },
                    isActive: true
                }
            });
            if (!asmUser) {
                return res.status(400).json({ success: false, message: 'Selected ASM user is invalid or inactive' });
            }
        }

        const previousAsmId = dealer.asmId;
        await dealer.update({ asmId: asmUser ? asmUser.id : null });

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.DEALER_MAPPING,
            entityType: 'dealer_asm_mapping',
            entityId: dealer.id,
            entityLabel: `Dealer ${dealer.businessName || dealer.legalName || dealer.id}`,
            action: asmUser ? SYSTEM_AUDIT_ACTIONS.ASSIGNED : SYSTEM_AUDIT_ACTIONS.UNASSIGNED,
            description: asmUser
                ? `Assigned ASM ${asmUser.fullName || asmUser.id} to dealer ${dealer.businessName || dealer.legalName || dealer.id}`
                : `Removed ASM mapping from dealer ${dealer.businessName || dealer.legalName || dealer.id}`,
            oldData: { asmId: previousAsmId },
            newData: { asmId: asmUser ? asmUser.id : null, asmName: asmUser?.fullName || null }
        });

        res.json({ success: true, message: asmUserId ? 'ASM assigned to dealer successfully' : 'ASM mapping removed successfully' });
    } catch (error) {
        console.error('Save dealer ASM mapping error:', error);
        res.status(500).json({ success: false, message: 'Error saving dealer ASM mapping' });
    }
};

// --- SLA Configuration ---
export const getSlaConfigs = async (req: Request, res: Response) => {
    try {
        const configs = await db.SLAConfiguration.findAll({
            include: [
                { model: db.SLAReminder, as: 'reminders' },
                { model: db.SLAEscalationConfig, as: 'escalationConfigs' }
            ],
            order: [['activityName', 'ASC']]
        });
        res.json({ success: true, data: configs });
    } catch (error) {
        console.error('Get SLA configs error:', error);
        res.status(500).json({ success: false, message: 'Error fetching SLA configurations' });
    }
};

export const saveSlaConfig = async (req: Request, res: Response) => {
    const transaction = await db.sequelize.transaction();
    try {
        const { id, activityName, ownerRole, tatHours, tatUnit, isActive, reminders, escalationConfigs } = req.body;
        
        let config;
        let previousSnapshot: Record<string, unknown> | null = null;
        const isUpdate = Boolean(id);
        if (id) {
            config = await db.SLAConfiguration.findByPk(id, { transaction });
            if (!config) throw new Error('SLA Configuration not found');
            previousSnapshot = {
                activityName: config.activityName,
                ownerRole: config.ownerRole,
                tatHours: config.tatHours,
                tatUnit: config.tatUnit,
                isActive: config.isActive
            };
            await config.update({ activityName, ownerRole, tatHours, tatUnit, isActive }, { transaction });
        } else {
            config = await db.SLAConfiguration.create({ activityName, ownerRole, tatHours, tatUnit, isActive: isActive !== undefined ? isActive : true }, { transaction });
        }

        // Handle Reminders
        await db.SLAReminder.destroy({ where: { slaConfigId: config.id }, transaction });
        if (Array.isArray(reminders)) {
            for (const r of reminders) {
                await db.SLAReminder.create({
                    slaConfigId: config.id,
                    timeValue: r.timeValue,
                    timeUnit: r.timeUnit,
                    isEnabled: true
                }, { transaction });
            }
        }

        // Handle Escalations
        await db.SLAEscalationConfig.destroy({ where: { slaConfigId: config.id }, transaction });
        if (Array.isArray(escalationConfigs)) {
            for (const e of escalationConfigs) {
                await db.SLAEscalationConfig.create({
                    slaConfigId: config.id,
                    level: e.level,
                    timeValue: e.timeValue,
                    timeUnit: e.timeUnit,
                    notifyEmail: e.notifyEmail,
                    notifyChannel: 'email'
                }, { transaction });
            }
        }

        await transaction.commit();

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.SLA_CONFIG,
            entityType: 'sla_configuration',
            entityId: config.id,
            entityLabel: `SLA · ${activityName}`,
            action: isUpdate ? SYSTEM_AUDIT_ACTIONS.UPDATED : SYSTEM_AUDIT_ACTIONS.CREATED,
            description: `${isUpdate ? 'Updated' : 'Created'} SLA "${activityName}" — owner ${ownerRole}, ${tatHours} ${tatUnit}, reminders ${
                Array.isArray(reminders) ? reminders.length : 0
            }, escalations ${Array.isArray(escalationConfigs) ? escalationConfigs.length : 0}`,
            oldData: previousSnapshot,
            newData: {
                activityName,
                ownerRole,
                tatHours,
                tatUnit,
                isActive,
                reminderCount: Array.isArray(reminders) ? reminders.length : 0,
                escalationCount: Array.isArray(escalationConfigs) ? escalationConfigs.length : 0
            }
        });

        res.json({ success: true, data: config });
    } catch (error) {
        await transaction.rollback();
        console.error('Save SLA config error:', error);
        res.status(500).json({ success: false, message: 'Error saving SLA configuration' });
    }
};

export const initializeDefaultSlas = async (req: Request, res: Response) => {
    const transaction = await db.sequelize.transaction();
    try {
        const { SLA_STAGE_CATALOG } = await import('../../common/config/slaStageCatalog.js');
        const { seedSlaCatalogEntries } = await import('../../common/utils/slaSeedUtils.js');

        await seedSlaCatalogEntries(db, SLA_STAGE_CATALOG, transaction);

        await transaction.commit();

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.SLA_CONFIG,
            entityType: 'sla_defaults',
            entityId: null,
            entityLabel: `Default SLA matrix (${SLA_STAGE_CATALOG.length} stages)`,
            action: SYSTEM_AUDIT_ACTIONS.INITIALIZED,
            description: `Initialized SLA catalog aligned to workflow stage names (${SLA_STAGE_CATALOG.length} activities)`,
            metadata: { stageCount: SLA_STAGE_CATALOG.length }
        });

        res.json({
            success: true,
            message: `SLA configurations initialized (${SLA_STAGE_CATALOG.length} activities across all modules)`
        });
    } catch (error) {
        await transaction.rollback();
        console.error('Init SLA error:', error);
        res.status(500).json({ success: false, message: 'Error initializing SLAs' });
    }
};

