
import db from '../database/models/index.js';
import { WorkflowService } from './WorkflowService.js';
import { APPLICATION_STATUS } from '../common/config/constants.js';

const LOA_STAGE_CODE = 'LOA_APPROVAL';
const LOI_STAGE_CODE = 'LOI_APPROVAL';

export class WorkflowIntegrityService {
    /**
     * Ensures an application's state is consistent with its approvals and policies.
     * This fixes stalled applications automatically without manual "healing" scripts.
     */
    static async synchronizeApplicationState(applicationId: string) {
        try {
            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(applicationId);
            const application = await db.Application.findOne({
                where: isUUID ? { [db.Sequelize.Op.or]: [{ id: applicationId }, { applicationId }] } : { applicationId }
            });
            
            if (!application) return;

            // LOA STAGE INTEGRITY
            if (['LOA Pending', 'LOA Issued'].includes(application.overallStatus)) {
                await this.syncLoaIntegrity(application);
            }

            // LOI STAGE INTEGRITY
            // Include legacy DB label "Security Details" until data migration completes.
            const loiPreIssuedStatuses = [
                APPLICATION_STATUS.LOI_IN_PROGRESS,
                APPLICATION_STATUS.PAYMENT_PENDING,
                APPLICATION_STATUS.SECURITY_DETAILS,
                'Security Details'
            ];
            if (loiPreIssuedStatuses.includes(application.overallStatus)) {
                await this.syncLoiIntegrity(application);
            }

            // DEALER CODE INTEGRITY (Parallelizing Architecture/Statutory)
            if ([APPLICATION_STATUS.DEALER_CODE_GENERATION, APPLICATION_STATUS.ARCHITECTURE_TEAM_ASSIGNED, APPLICATION_STATUS.ARCHITECTURE_DOCUMENT_UPLOAD, APPLICATION_STATUS.ARCHITECTURE_TEAM_COMPLETION].includes(application.overallStatus) || application.overallStatus.includes('Statutory')) {
                await this.syncDealerCodeIntegrity(application);
            }

            // Other stages can be added here...
        } catch (error) {
            console.error(`[WorkflowIntegrityService] Error syncing app ${applicationId}:`, error);
        }
    }

    private static async syncDealerCodeIntegrity(application: any) {
        // Check if Dealer codes exist
        const dealerCode = await db.DealerCode.findOne({
            where: { applicationId: application.id, status: 'Active' }
        });

        if (dealerCode) {
            console.log(`[WorkflowIntegrityService] Dealer Codes exist for ${application.applicationId}. Transitioning to LOA Pending...`);
            
            await WorkflowService.transitionApplication(application, APPLICATION_STATUS.LOA_PENDING, null, {
                reason: 'Auto-transitioned by Integrity Service: Dealer codes generated. Architecture/Statutory work will proceed in parallel.',
                progressPercentage: 85
            });
        }
    }

    private static async syncLoaIntegrity(application: any) {
        // 1. Migrate legacy approvals if they exist but aren't in the new system
        const legacyApprovals = await db.LoaApproval.findAll({
            where: { action: 'Approved' },
            include: [{ 
                model: db.LoaRequest, 
                as: 'request', 
                where: { applicationId: application.id } 
            }]
        });

        for (const legacy of legacyApprovals) {
            if (legacy.approverId) {
                await db.StageApprovalAction.findOrCreate({
                    where: {
                        applicationId: application.id,
                        stageCode: LOA_STAGE_CODE,
                        actorUserId: legacy.approverId
                    },
                    defaults: {
                        actorRole: legacy.approverRole,
                        decision: 'Approved',
                        remarks: legacy.remarks || 'Migrated from legacy approval'
                    }
                });
            }
        }

        // 2. Evaluate policy and transition if met
        const { policyMet } = await WorkflowService.evaluateStagePolicy(application.id, LOA_STAGE_CODE);
        
        if (policyMet && application.overallStatus !== APPLICATION_STATUS.EOR_IN_PROGRESS) {
            console.log(`[WorkflowIntegrityService] Policy met for LOA on ${application.applicationId}. Transitioning...`);
            
            // Ensure LoaRequest is also updated
            const request = await db.LoaRequest.findOne({ where: { applicationId: application.id } });
            if (request && request.status !== 'Approved') {
                await request.update({ status: 'Approved', approvedAt: new Date() });
            }

            await WorkflowService.transitionApplication(application, APPLICATION_STATUS.EOR_IN_PROGRESS, null, {
                reason: 'Auto-transitioned by Integrity Service: Approval condition satisfied.',
                progressPercentage: 97
            });
        }
    }

    private static async syncLoiIntegrity(application: any) {
        // 1. Evaluate policy
        const { policyMet } = await WorkflowService.evaluateStagePolicy(application.id, LOI_STAGE_CODE);
        
        // 2. Check for Security Deposit verification
        const deposit = await db.SecurityDeposit.findOne({
            where: { applicationId: application.id, depositType: 'SECURITY_DEPOSIT', status: 'Verified' }
        });

        if (policyMet && deposit) {
            console.log(`[WorkflowIntegrityService] Policy met and payment verified for LOI on ${application.applicationId}. Aligning to Security Deposit for admin approval before LOI Issued.`);

            // Ensure LoiRequest is also updated
            const request = await db.LoiRequest.findOne({ where: { applicationId: application.id } });
            if (request && request.status !== 'Approved') {
                await request.update({ status: 'Approved', approvedAt: new Date() });
            }

            await WorkflowService.transitionApplication(application, APPLICATION_STATUS.SECURITY_DETAILS, null, {
                reason: 'Integrity sync: LOI policy and deposit verified — use Security Deposit admin approval to reach LOI Issued.',
                progressPercentage: 78
            });
        }
    }
}
