import db from '../../database/models/index.js';
const { ApplicationProgress } = db;

export const ONBOARDING_STAGES = [
    { name: 'Submitted', order: 1 },
    { name: 'Questionnaire', order: 2 },
    { name: 'Shortlist', order: 3 },
    { name: '1st Level Interview', order: 4 },
    { name: '2nd Level Interview', order: 5 },
    { name: '3rd Level Interview', order: 6 },
    { name: 'FDD', order: 7 },
    { name: 'LOI Approval', order: 8 },
    { name: 'Security Deposit', order: 9 },
    { name: 'LOI Issue', order: 10 },
    { name: 'Dealer Code Generation', order: 11 },
    { name: 'Architecture Work', order: 12 },
    { name: 'Statutory Work', order: 12 }, // UNIFIED with Architecture
    { name: 'LOA', order: 13 },
    { name: 'EOR Complete', order: 14 },
    { name: 'Inauguration', order: 15 },
    { name: 'Onboarded', order: 16 }
];

/**
 * Updates application progress for a specific stage
 */
export const updateApplicationProgress = async (applicationId: string, stageName: string, status: 'pending' | 'active' | 'completed', percentage: number = 0) => {
    try {
        const stage = ONBOARDING_STAGES.find(s => s.name === stageName);
        if (!stage) return;

        const [progress, created] = await ApplicationProgress.findOrCreate({
            where: { applicationId, stageName },
            defaults: {
                stageOrder: stage.order,
                status,
                completionPercentage: percentage,
                stageStartedAt: status === 'active' ? new Date() : null,
                stageCompletedAt: status === 'completed' ? new Date() : null
            }
        });

        if (!created) {
            const updates: any = { status, completionPercentage: percentage };
            if (status === 'active' && !progress.stageStartedAt) {
                updates.stageStartedAt = new Date();
            }
            if (status === 'completed' && !progress.stageCompletedAt) {
                updates.stageCompletedAt = new Date();
            }
            await progress.update(updates);
        }

        // Whenever a stage is marked 'active' or 'completed', 
        // all previous stages MUST exist and be marked 'completed'.
        // EXCEPTION: Parallel stages (Architecture/Statutory) share the same order, 
        // so we only autocomplete stages with order < current order.
        if (status === 'active' || status === 'completed') {
            const previousStages = ONBOARDING_STAGES.filter(s => s.order < stage.order);
            for (const prev of previousStages) {
                await ApplicationProgress.findOrCreate({
                    where: { applicationId, stageName: prev.name },
                    defaults: {
                        stageOrder: prev.order,
                        status: 'completed',
                        completionPercentage: 100,
                        stageCompletedAt: new Date()
                    }
                });
            }

            // Also update any existing ones that weren't completed
            await ApplicationProgress.update(
                { status: 'completed', completionPercentage: 100, stageCompletedAt: new Date() },
                { 
                    where: { 
                        applicationId, 
                        stageOrder: { [db.Sequelize.Op.lt]: stage.order },
                        status: { [db.Sequelize.Op.ne]: 'completed' }
                    } 
                }
            );
        }

        return progress;
    } catch (error) {
        console.error('Error updating application progress:', error);
    }
};

/**
 * Maps application `overallStatus` to the pipeline stage label used in ApplicationProgress
 * and (via WorkflowService) `Application.currentStage` + audit `newData.stage`.
 * Keeps audit trail aligned with the post-LOI milestones (dealer code → LOA → EOR → inauguration).
 */
export const PIPELINE_STAGE_LABEL_BY_OVERALL_STATUS: Record<string, string> = {
    Submitted: 'Submitted',
    'Questionnaire Pending': 'Questionnaire',
    'Questionnaire Completed': 'Questionnaire',
    Shortlisted: 'Shortlist',
    'Level 1 Interview Pending': '1st Level Interview',
    'Level 1 Approved': '1st Level Interview',
    'Level 2 Interview Pending': '2nd Level Interview',
    'Level 2 Approved': '2nd Level Interview',
    'Level 2 Recommended': '2nd Level Interview',
    'Level 3 Interview Pending': '3rd Level Interview',
    'Level 3 Approved': '3rd Level Interview',
    'FDD Verification': 'FDD',
    'LOI In Progress': 'LOI Approval',
    /** @deprecated DB rows may still use pre-rename label until migrated */
    'Security Details': 'Security Deposit',
    'Security Deposit': 'Security Deposit',
    'Payment Pending': 'Security Deposit',
    'LOI Issued': 'LOI Issue',
    'Statutory LOI Ack': 'LOI Issue',
    'Dealer Code Generation': 'Dealer Code Generation',
    'Architecture Team Assigned': 'Architecture Work',
    'Architecture Document Upload': 'Architecture Work',
    'Architecture Team Completion': 'Architecture Work',
    'Architecture Work': 'Architecture Work',
    'Statutory GST': 'Statutory Work',
    'Statutory PAN': 'Statutory Work',
    'Statutory Nodal': 'Statutory Work',
    'Statutory Check': 'Statutory Work',
    'Statutory Partnership': 'Statutory Work',
    'Statutory Firm Reg': 'Statutory Work',
    'Statutory Rental': 'Statutory Work',
    'Statutory Virtual Code': 'Statutory Work',
    'Statutory Domain': 'Statutory Work',
    'Statutory MSD': 'Statutory Work',
    'Statutory Work': 'Statutory Work',
    'LOA Pending': 'LOA',
    'LOA Issued': 'LOA',
    'LOA Rejected': 'LOA',
    'LOI Rejected': 'LOI Issue',
    'EOR In Progress': 'EOR Complete',
    'EOR Complete': 'EOR Complete',
    Inauguration: 'Inauguration',
    Approved: 'Inauguration',
    Onboarded: 'Onboarded',
    Rejected: 'Rejected',
    Disqualified: 'Disqualified',
    'Returned to FDD': 'FDD',
    Pending: 'Submitted',
    'In Review': 'Shortlist',
};

/**
 * Syncs all progress stages based on current overall status
 */
export const syncApplicationProgress = async (applicationId: string, overallStatus: string) => {
    const currentStageName = PIPELINE_STAGE_LABEL_BY_OVERALL_STATUS[overallStatus];
    if (currentStageName) {
        const currentStage = ONBOARDING_STAGES.find(s => s.name === currentStageName);
        if (currentStage) {
            // Statuses that imply the CURRENT stage (single or both parallel) is finished
            const completionStatuses = [
                'Submitted', 'Questionnaire Completed', 'Shortlisted', 'Level 1 Approved', 
                'Level 2 Approved', 'Level 2 Recommended', 'Level 3 Approved', 
                'EOR Complete', 'Inauguration', 'Approved', 'Onboarded'
            ];

            const isCurrentStageFinished = completionStatuses.includes(overallStatus);

            // Fetch application to check model-driven parallel status
            const application = await db.Application.findByPk(applicationId);

            // Robust Sync: Prepare ALL stages for batch processing
            const upsertData: any[] = [];
            for (const stage of ONBOARDING_STAGES) {
                let status: 'pending' | 'active' | 'completed' = 'pending';
                let percentage = 0;

                if (stage.order < currentStage.order) {
                    status = 'completed';
                    percentage = 100;
                } else if (stage.order === currentStage.order) {
                    status = isCurrentStageFinished ? 'completed' : 'active';
                    percentage = isCurrentStageFinished ? 100 : 50;
                    
                    if (stage.name === 'Architecture Work' && application) {
                        status = application.architectureStatus === 'COMPLETED' ? 'completed' : 
                                 (application.architectureStatus === 'IN_PROGRESS' || currentStage.name === 'Architecture Work' || isCurrentStageFinished) ? 'active' : 'pending';
                        percentage = status === 'completed' ? 100 : status === 'active' ? 50 : 0;
                    } 
                    if (stage.name === 'Statutory Work' && application) {
                        status = application.statutoryStatus === 'COMPLETED' ? 'completed' : 
                                 (application.statutoryStatus === 'IN_PROGRESS' || currentStage.name === 'Statutory Work' || isCurrentStageFinished) ? 'active' : 'pending';
                        percentage = status === 'completed' ? 100 : status === 'active' ? 50 : 0;
                    }
                }
                
                upsertData.push({
                    applicationId,
                    stageName: stage.name,
                    stageOrder: stage.order,
                    status,
                    completionPercentage: percentage,
                    stageStartedAt: (status === 'active' || status === 'completed') ? new Date() : null,
                    stageCompletedAt: status === 'completed' ? new Date() : null
                });
            }

            // DB Duplication Prevention without Schema Changes (Healing corrupted data loops)
            const existingRecords = await ApplicationProgress.findAll({ where: { applicationId } });
            const seenStages = new Set<string>();

            // Purge any ghost duplicates created by old logic
            for (const record of existingRecords) {
                if (seenStages.has(record.stageName)) {
                    await record.destroy(); 
                } else {
                    seenStages.add(record.stageName);
                }
            }

            // Perform single row updates/inserts to enforce exact 1:1 mapping safely
            const cleanedRecords = await ApplicationProgress.findAll({ where: { applicationId } });

            for (const data of upsertData) {
                const existing = cleanedRecords.find((r: any) => r.stageName === data.stageName);
                if (existing) {
                    await existing.update({
                        stageOrder: data.stageOrder,
                        status: data.status,
                        completionPercentage: data.completionPercentage,
                        stageStartedAt: data.stageStartedAt || existing.stageStartedAt,
                        stageCompletedAt: data.stageCompletedAt || existing.stageCompletedAt
                    });
                } else {
                    await ApplicationProgress.create(data);
                }
            }
        }
    }
};
