import { Request, Response } from 'express';
import { Op } from 'sequelize';
import db from '../../database/models/index.js';
const { EorChecklist, EorChecklistItem, OnboardingDocument, RelocationDocument } = db;
import { AuthRequest } from '../../types/express.types.js';
import { NotificationService } from '../../services/NotificationService.js';
import { ROLES } from '../../common/config/constants.js';
import { getFrontendBaseUrl } from '../../common/utils/frontendUrl.js';

/** Default EOR rows for relocation (SRS 12.2.8) — must stay aligned with relocation required-doc labels. */
export const RELOCATION_EOR_DEFAULT_ITEMS = [
    { itemType: 'Property', description: 'Property documents for new location' },
    { itemType: 'Property', description: 'Lease / Rental agreement' },
    { itemType: 'Property', description: 'Layout / Floor plan of new location' },
    { itemType: 'Infrastructure', description: 'Photos of new location' },
    { itemType: 'Infrastructure', description: 'Locality map / Building plan approval' },
    { itemType: 'Statutory', description: 'NOC from current landlord' },
    { itemType: 'Statutory', description: 'Municipal approvals (Fire safety / Pollution clearance)' },
    { itemType: 'Utility', description: 'Electricity & Water supply documents' }
] as const;

/**
 * Maps `RelocationDocument.documentType` (same strings as relocation required-doc UI) to EOR checklist row text.
 */
const RELOCATION_UPLOAD_TYPE_TO_EOR_DESCRIPTION: Record<string, string> = {
    'Property documents for new location': 'Property documents for new location',
    'Lease/Rental agreement for new location': 'Lease / Rental agreement',
    'NOC from current landlord': 'NOC from current landlord',
    'Municipal approvals': 'Municipal approvals (Fire safety / Pollution clearance)',
    'Fire safety certificate': 'Municipal approvals (Fire safety / Pollution clearance)',
    'Pollution clearance': 'Municipal approvals (Fire safety / Pollution clearance)',
    'Layout/Floor plan of new location': 'Layout / Floor plan of new location',
    'Photos of new location': 'Photos of new location',
    'Locality map': 'Locality map / Building plan approval',
    'Building plan approval': 'Locality map / Building plan approval',
    'Electricity connection documents': 'Electricity & Water supply documents',
    'Water supply documents': 'Electricity & Water supply documents'
};

async function mapRelocationDocumentsToEorItems(checklistId: string, relocationId: string) {
    const docs = await RelocationDocument.findAll({
        where: {
            relocationId,
            status: { [Op.notIn]: ['Rejected'] }
        }
    });
    for (const doc of docs) {
        const dt = String((doc as any).documentType || '').trim();
        const eorDesc = RELOCATION_UPLOAD_TYPE_TO_EOR_DESCRIPTION[dt];
        if (!eorDesc) continue;
        const verified = String((doc as any).status || '').toLowerCase() === 'verified';

        let item = await EorChecklistItem.findOne({
            where: {
                checklistId,
                description: { [Op.iLike]: eorDesc },
                proofDocumentId: { [Op.is]: null }
            }
        });
        if (!item) {
            const linked = await EorChecklistItem.findOne({
                where: {
                    checklistId,
                    description: { [Op.iLike]: eorDesc },
                    proofDocumentId: (doc as any).id
                }
            });
            if (linked && verified) {
                await linked.update({ isCompliant: true });
            }
            continue;
        }

        await item.update({
            proofDocumentId: (doc as any).id,
            isCompliant: verified ? true : item.isCompliant
        });
    }
}

/**
 * Relocation flow historically called `EorChecklist.findOrCreate` only, so checklists existed with **zero items**
 * and no link to `relocation_documents`. Heal by seeding default rows and attaching proofs by document type.
 */
export async function ensureRelocationEorChecklistSeeded(relocationId: string): Promise<void> {
    const checklist = await EorChecklist.findOne({ where: { relocationId } });
    if (!checklist) return;

    const itemCount = await EorChecklistItem.count({ where: { checklistId: checklist.id } });
    if (itemCount === 0) {
        const compliantDefault = String(checklist.status || '').toLowerCase() === 'completed';
        await EorChecklistItem.bulkCreate(
            RELOCATION_EOR_DEFAULT_ITEMS.map((item) => ({
                itemType: item.itemType,
                description: item.description,
                checklistId: checklist.id,
                isCompliant: compliantDefault
            }))
        );
    }

    await mapRelocationDocumentsToEorItems(checklist.id, relocationId);
}

export const getChecklist = async (req: Request, res: Response) => {
    try {
        const { applicationId, relocationId } = req.params;

        // Resolve human-readable applicationId (e.g. APP-2026-79CE90) to UUID
        let resolvedAppId = applicationId as string;
        if (applicationId) {
            const appIdStr = applicationId as string;
            const isUUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(appIdStr);
            if (!isUUID) {
                const app = await db.Application.findOne({ where: { applicationId: appIdStr } });
                if (!app) {
                    res.status(404).json({ success: false, message: 'Application not found' });
                    return;
                }
                resolvedAppId = app.id;
            }
        }

        // Resolve relocation route param (UUID or REL-2026-xxxx) to UUID for DB lookup
        let resolvedRelocationId: string | undefined;
        if (relocationId) {
            const relStr = relocationId as string;
            const isRelUUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(relStr);
            if (isRelUUID) {
                resolvedRelocationId = relStr;
            } else {
                const rel = await db.RelocationRequest.findOne({ where: { requestId: relStr } });
                if (!rel) {
                    res.status(404).json({ success: false, message: 'Relocation request not found' });
                    return;
                }
                resolvedRelocationId = rel.id;
            }
        }

        let checklist = await EorChecklist.findOne({
            where: resolvedRelocationId ? { relocationId: resolvedRelocationId } : { applicationId: resolvedAppId },
            include: [{ model: EorChecklistItem, as: 'items' }]
        });

        if (!checklist) {
            res.status(404).json({ success: false, message: 'Checklist not found' });
            return;
        }

        if (resolvedRelocationId) {
            await ensureRelocationEorChecklistSeeded(resolvedRelocationId);
            checklist = await EorChecklist.findOne({
                where: { relocationId: resolvedRelocationId },
                include: [{ model: EorChecklistItem, as: 'items' }]
            });
            if (!checklist) {
                res.status(404).json({ success: false, message: 'Checklist not found' });
                return;
            }
        }

        const items = checklist.items || [];
        const proofDocIds = items.map((i: any) => i.proofDocumentId).filter(Boolean);

        let payload: any = checklist.toJSON ? checklist.toJSON() : checklist;

        if (proofDocIds.length > 0) {
            let docs = [];
            if (resolvedRelocationId) {
                docs = await RelocationDocument.findAll({ where: { id: proofDocIds } });
            } else {
                docs = await OnboardingDocument.findAll({ where: { id: proofDocIds } });
            }

            const docsMap = new Map(docs.map((d: any) => [d.id, d]));
            payload = { ...payload };
            payload.items = (payload.items || []).map((item: any) => ({
                ...item,
                proofDocument: docsMap.get(item.proofDocumentId) || null
            }));
        }

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

export const createChecklist = async (req: AuthRequest, res: Response) => {
    try {
        const { applicationId: rawAppId, relocationId } = req.body;

        if (!rawAppId && !relocationId) {
            return res.status(400).json({ success: false, message: 'applicationId or relocationId is required' });
        }

        // Resolve applicationId to UUID (handles readable IDs like APP-2026-79CE90)
        let resolvedAppId: string | null = null;
        if (rawAppId) {
            const isUUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(rawAppId);
            const application = isUUID
                ? await db.Application.findByPk(rawAppId)
                : await db.Application.findOne({ where: { applicationId: rawAppId } });
            if (!application) return res.status(404).json({ success: false, message: 'Application not found' });
            resolvedAppId = application.id;
        } else if (relocationId) {
            const relocation = await db.RelocationRequest.findByPk(relocationId);
            if (!relocation) return res.status(404).json({ success: false, message: 'Relocation request not found' });
        }

        const [checklist, created] = await EorChecklist.findOrCreate({
            where: relocationId ? { relocationId } : { applicationId: resolvedAppId },
            defaults: { 
                status: 'In Progress',
                applicationId: resolvedAppId || null,
                relocationId: relocationId || null
            }
        });


        if (created) {
            // Define Default Mandatory Items per SRS/Frontend
            let defaultItems: { itemType: string; description: string }[] = [];

            if (relocationId) {
                defaultItems = [...RELOCATION_EOR_DEFAULT_ITEMS];
            } else {
                // Onboarding Default
                defaultItems = [
                    { itemType: 'Sales', description: 'Sales Standards' },
                    { itemType: 'Service', description: 'Service & Spares' },
                    { itemType: 'IT', description: 'DMS infra' },
                    { itemType: 'Training', description: 'Manpower Training' },
                    { itemType: 'Statutory', description: 'Trade certificate with test ride bikes registration' },
                    { itemType: 'Statutory', description: 'GST certificate including Accessories & Apparels billing' },
                    { itemType: 'Finance', description: 'Inventory Funding' },
                    { itemType: 'IT', description: 'Virtual code availability' },
                    { itemType: 'Finance', description: 'Vendor payments' },
                    { itemType: 'Marketing', description: 'Details for website submission' },
                    { itemType: 'Insurance', description: 'Infra Insurance both Showroom and Service center' },
                    { itemType: 'IT', description: 'Auto ordering' }
                ];
            }

            const itemsData = defaultItems.map(item => ({
                ...item,
                checklistId: checklist.id,
                isCompliant: false
            }));

            await EorChecklistItem.bulkCreate(itemsData);

            // AUTO-MAP existing documents from OnboardingDocument table
            if (resolvedAppId) {
                const existingDocs = await OnboardingDocument.findAll({
                    where: { applicationId: resolvedAppId, status: 'active' }
                });

                if (existingDocs.length > 0) {
                    const typeMap: any = {
                        'GST Certificate': 'GST certificate including Accessories & Apparels billing',
                        'Virtual Code Confirmation': 'Virtual code availability',
                        'Trade Certificate': 'Trade certificate with test ride bikes registration',
                        'DMS Infra Details': 'DMS infra'
                    };

                    for (const doc of existingDocs) {
                        const targetDescription = typeMap[doc.documentType] || doc.documentType;
                        await EorChecklistItem.update(
                            { proofDocumentId: doc.id },
                            { where: { checklistId: checklist.id, description: { [Op.iLike]: targetDescription.trim() } } }
                        );
                    }
                }
            } else if (relocationId) {
                await mapRelocationDocumentsToEorItems(checklist.id, relocationId);
            }
        }

        // Status transition will be handled by the global handleApprove workflow or explicit trigger
        // await application.update({ overallStatus: 'EOR In Progress' });

        res.status(201).json({ success: true, message: 'EOR Checklist initiated with default items', data: checklist });
    } catch (error) {
        console.error('Create EOR checklist error:', error);
        res.status(500).json({ success: false, message: 'Error creating checklist' });
    }
}

export const updateItem = async (req: AuthRequest, res: Response) => {
    try {
        const { checklistId } = req.params;
        const { itemType, description, isCompliant, remarks, proofDocumentId } = req.body;

        let item = await EorChecklistItem.findOne({
            where: { checklistId, description }
        });

        if (item) {
            await item.update({ isCompliant, remarks, proofDocumentId, itemType });
        } else {
            item = await EorChecklistItem.create({
                checklistId,
                itemType,
                description,
                isCompliant,
                remarks,
                proofDocumentId
            });
        }

        res.status(201).json({ success: true, message: 'Item added/updated', data: item });
    } catch (error) {
        console.error('Update EOR item error:', error);
        res.status(500).json({ success: false, message: 'Error updating item' });
    }
};

export const submitAudit = async (req: AuthRequest, res: Response) => {
    try {
        const { checklistId } = req.params; // or ID
        const { status, overallComments } = req.body;

        await EorChecklist.update(
            { status, overallComments, auditDate: new Date(), auditorId: req.user?.id },
            { where: { id: checklistId } }
        );

        if (status === 'Completed') {
            const checklist = await EorChecklist.findByPk(checklistId);
            if (checklist) {
                if (checklist.applicationId) {
                    await db.Application.update({
                        overallStatus: 'Inauguration',
                        progressPercentage: 100
                    }, { where: { id: checklist.applicationId } });

                    // Update Progress Tracking
                    const { updateApplicationProgress } = await import('../../common/utils/progress.js');
                    await updateApplicationProgress(checklist.applicationId, 'EOR Complete', 'completed', 100);
                    await updateApplicationProgress(checklist.applicationId, 'Inauguration', 'active', 50);

                    // SRS §6.19.3.4 — Readiness alert to DD-Head and NBH on EOR 100% completion
                    const app = await db.Application.findByPk(checklist.applicationId);
                    const eorAlertRoles = [ROLES.DD_HEAD, ROLES.NBH, ROLES.DD_ADMIN];
                    for (const role of eorAlertRoles) {
                        const roleUsers = await db.User.findAll({ where: { roleCode: role } });
                        for (const u of roleUsers) {
                            NotificationService.notify(u.id, u.email, {
                                title: `EOR Completed: ${app?.applicationId || checklist.applicationId}`,
                                message: `EOR checklist is 100% complete for ${app?.applicantName || 'the applicant'}. Dealership is ready for inauguration.`,
                                channels: ['system', 'email'],
                                templateCode: 'EOR_COMPLETED',
                                placeholders: {
                                    applicantName: app?.applicantName || '',
                                    applicationId: app?.applicationId || '',
                                    link: `${getFrontendBaseUrl()}/applications/${checklist.applicationId}`,
                                    ctaLabel: 'View Application'
                                }
                            }).catch((e: any) => console.error('[EOR] Completion notify failed:', e));
                        }
                    }
                } else if (checklist.relocationId) {
                    await db.RelocationRequest.update({
                        status: 'Completed',
                        progressPercentage: 100,
                        currentStage: 'Completed'
                    }, { where: { id: checklist.relocationId } });
                    
                    // SRS §6.19.3.4 — Relocation EOR complete — notify DD-Admin
                    const adminUsers = await db.User.findAll({ where: { roleCode: ROLES.DD_ADMIN } });
                    for (const u of adminUsers) {
                        NotificationService.notify(u.id, u.email, {
                            title: `Relocation EOR Completed`,
                            message: `The EOR checklist for relocation ${checklist.relocationId} has been fully verified.`,
                            channels: ['system', 'email'],
                            templateCode: 'EOR_COMPLETED',
                            placeholders: {
                                applicantName: '',
                                applicationId: checklist.relocationId,
                                link: `${getFrontendBaseUrl()}/relocation-requests/${checklist.relocationId}`,
                                ctaLabel: 'View Request'
                            }
                        }).catch((e: any) => console.error('[EOR] Relocation notify failed:', e));
                    }
                }
            }
        }

        res.json({ success: true, message: 'EOR Audit submitted' });
    } catch (error) {
        res.status(500).json({ success: false, message: 'Error submitting audit' });
    }
};
