const args = Object.fromEntries(
    process.argv.slice(2)
        .map(arg => arg.replace(/^--/, '').split('='))
        .map(([k, v]) => [k, v ?? 'true'])
);
const BASE_URL = args.baseUrl || process.env.BASE_URL || 'http://localhost:5000/api';
// const BASE_URL = 'https://dealeronboarding-uat.royalenfield.com/api';
const PASSWORD = 'Admin@123';
const STEP_DELAY_MS = Number(args.delayMs || 500);
const SHOULD_SKIP_CLEARANCES = String(args.skipClearances || 'false') === 'true';
const SHOULD_SKIP_FINAL_SETTLEMENT = String(args.skipSettlement || 'false') === 'true';

const EMAILS = {
    DD_ADMIN: 'lince@royalenfield.com',
    DEALER: args.dealerEmail,
    ASM: 'abhishek@royalenfield.com',
    RBM: 'manish@royalenfield.com',
    DD_ZM: 'piyush@royalenfield.com',
    ZBH: 'manav@royalenfield.com',
    DD_LEAD: 'jaya@royalenfield.com',
    DD_HEAD: 'ganesh@royalenfield.com',
    NBH: 'yashwin@royalenfield.com',
    LEGAL: 'legal@royalenfield.com',
    FINANCE: 'finance@royalenfield.com',
    SALES: 'sales@royalenfield.com',
    SERVICE: 'service@royalenfield.com',
    SPARES: 'spares@royalenfield.com',
    ACCOUNTS: 'accounts@royalenfield.com',
    WARRANTY: 'warranty@royalenfield.com',
    MARKETING: 'marketing@royalenfield.com',
    HR: 'hr@royalenfield.com',
    IT: 'it@royalenfield.com',
    LOGISTICS: 'logistics@royalenfield.com',
    QUALITY: 'quality@royalenfield.com',
    APPAREL: 'apparel@royalenfield.com',
    DMS: 'dms@royalenfield.com'
};

async function resolveDealerAsmEmail(adminToken, dealerEmail) {
    try {
        const res = await apiRequest('/master/dealer-asm-mappings', 'GET', null, adminToken);
        const rows = res?.data?.dealers || [];
        const match = rows.find((d) => String(d?.dealerUser?.email || '').toLowerCase() === String(dealerEmail || '').toLowerCase());
        return match?.assignedAsm?.email || null;
    } catch (e) {
        return null;
    }
}

async function apiRequest(endpoint, method = 'GET', body = null, token = null) {
    const headers = { 'Content-Type': 'application/json' };
    if (token) headers['Authorization'] = `Bearer ${token}`;

    const config = { method, headers };
    if (body) config.body = JSON.stringify(body);

    const response = await fetch(`${BASE_URL}${endpoint}`, config);
    const data = await response.json();

    if (!response.ok) {
        throw new Error(`API Error ${method} ${endpoint}: ${JSON.stringify(data)}`);
    }
    return data;
}

async function login(email) {
    if (!login.cache) login.cache = {};
    if (login.cache[email]) return login.cache[email];
    const isInternal = email.endsWith('@royalenfield.com');
    const password = isInternal ? 'Admin@123' : 'Dealer@123';
    
    const data = await apiRequest('/auth/login', 'POST', { email, password });
    login.cache[email] = data.token;
    return login.cache[email];
}

const delay = (ms = STEP_DELAY_MS) => new Promise(res => setTimeout(res, ms));
const log = (step, msg) => console.log(`[STEP ${step}] ${msg}`);

async function run() {
    try {
        console.log('--- STARTING DEALER RESIGNATION E2E FLOW ---');

        const adminToken = await login(EMAILS.DD_ADMIN);
        const appsRes = await apiRequest('/onboarding/applications', 'GET', null, adminToken);
        const onboardedApps = appsRes.data.filter(a => (a.overallStatus || a.status || '').toLowerCase() === 'onboarded');

        if (onboardedApps.length === 0) throw new Error('No onboarded applications found for resignation test.');
        
        // 1.0 Find an active Dealer and Login
        let targetApp = null;
        let dealerToken = null;

        for (const app of onboardedApps) {
            try {
                process.stdout.write(`Testing login for ${app.email}... `);
                const dealerData = await apiRequest('/auth/login', 'POST', { 
                    email: app.email, 
                    password: 'Dealer@123' 
                });
                dealerToken = dealerData.token;
                targetApp = app;
                console.log('SUCCESS');
                break;
            } catch (e) {
                console.log('FAILED (Deactivated)');
            }
        }

        if (!targetApp) throw new Error('All onboarded applications are deactivated. Run onboarding first.');

        console.log(`Targeting Application: ${targetApp.applicantName} (${targetApp.id}) - Email: ${targetApp.email}`);
        const asmFromArg = args.asmEmail;
        const asmFromMapping = asmFromArg || await resolveDealerAsmEmail(adminToken, targetApp.email);
        if (asmFromMapping) {
            EMAILS.ASM = asmFromMapping;
            console.log(`[INFO] Using ASM approver: ${EMAILS.ASM}`);
        } else {
            console.log(`[WARN] Dealer-level ASM not found. Falling back to default ASM email: ${EMAILS.ASM}`);
        }
        await delay();
        
        // 1.1 Discover Dealer's Outlet
        console.log(`[STEP 1.1] Discovering Outlets for Dealer...`);
        const dealerDashboard = await apiRequest('/dealer/dashboard', 'GET', null, dealerToken);
        const targetOutlet = dealerDashboard.data.outlets[0];
        await delay();
        
        if (!targetOutlet) throw new Error('No outlets found for this dealer. Ensure they are fully onboarded.');
        console.log(`Found Target Outlet: ${targetOutlet.name} (${targetOutlet.code})`);

        console.log(`[STEP 1.2] Dealer Submitting Resignation for Outlet...`);
        let resignationId = args.resignationId;
        if (!resignationId) {
            try {
                const createRes = await apiRequest('/self-service/resignations', 'POST', {
                    outletId: targetOutlet.id,
                    resignationType: 'Voluntary',
                    lastOperationalDateSales: new Date().toISOString().split('T')[0],
                    lastOperationalDateServices: new Date().toISOString().split('T')[0],
                    reason: 'Focusing on other business ventures',
                    remarks: 'Initiating voluntary resignation for E2E validation.'
                }, dealerToken);
                resignationId = createRes.resignation.id;
                log(1, `Resignation Created. ID: ${resignationId}`);
            } catch (e) {
                if (e.message.includes('already has an active resignation request')) {
                    console.log(`[STEP 1.2] Active resignation already exists. Fetching...`);
                    const activeResRes = await apiRequest('/self-service/resignations', 'GET', null, dealerToken);
                    const activeRes = (activeResRes.resignations || activeResRes.data).find(r => r.outletId === targetOutlet.id && !['Completed', 'Rejected'].includes(r.status));
                    resignationId = activeRes.id;
                    log(1, `Resuming with existing Resignation: ${resignationId}`);
                } else {
                    throw e;
                }
            }
        } else {
            log(1, `Resuming provided resignation: ${resignationId}`);
        }
        
        await delay();

        const approvals = [
            { stage: 'ASM', name: 'ASM', email: EMAILS.ASM, remarks: 'Verified physical assets and dealer intent. Recommended for resignation.' },
            { stage: 'RBM + DD-ZM Review', name: 'RBM', email: EMAILS.RBM, remarks: 'No active sales pipeline issues in the territory. Transition plan discussed.' },
            { stage: 'RBM + DD-ZM Review', name: 'DD-ZM', email: EMAILS.DD_ZM, remarks: 'Joint approval evaluated and verified by DD-ZM.' },
            { stage: 'ZBH', name: 'ZBH', email: EMAILS.ZBH, remarks: 'Zone-level resource reallocation planned. Approved.' },
            { stage: 'DD Lead', name: 'DD Lead', email: EMAILS.DD_LEAD, remarks: 'Dealer development criteria satisfied for exit.' },
            { stage: 'DD Head', name: 'DD Head', email: EMAILS.DD_HEAD, remarks: 'Dealer development head sign-off recorded. Recommended for NBH.' },
            { stage: 'NBH', name: 'NBH', email: EMAILS.NBH, remarks: 'HQ clearance granted. Proceed with F&F initiation.' },
            { stage: 'Legal', name: 'Legal Admin', email: EMAILS.LEGAL, remarks: 'Legal documentation verified. No active litigation found.' },
            { stage: 'DD Admin', name: 'DD Admin', email: EMAILS.DD_ADMIN, remarks: 'Administrative checks complete. Initiating termination of commercial contract.' }
        ];

        // Fetch resignation data to determine current stage for skipping
        const resignationData = await apiRequest(`/self-service/resignations/${resignationId}`, 'GET', null, adminToken);
        const currentStage = resignationData.resignation.currentStage;
        
        console.log(`Current Stage: ${currentStage}`);

        const stageOrder = [
            'Request Submitted', 'ASM', 'RBM + DD-ZM Review', 'ZBH', 'DD Lead', 'DD Head', 'NBH', 'Legal', 'DD Admin', 'F&F Initiated', 'Completed'
        ];

        let startStageIndex = stageOrder.indexOf(currentStage) === -1 ? 0 : stageOrder.indexOf(currentStage);
        const startingStage = stageOrder[startStageIndex];
        
        let startApproveIndex = approvals.findIndex(a => a.stage === startingStage);
        if (startApproveIndex === -1) startApproveIndex = 0;

        let currentStep = 2;
        for (let i = startApproveIndex; i < approvals.length; i++) {
            const actor = approvals[i];
            log(currentStep, `${actor.name} (${actor.email}) approving...`);
            const token = await login(actor.email);

            // Special Case: Legal Admin must upload 'Resignation Acceptance Letter' before approving
            if (actor.stage === 'Legal') {
                log(currentStep, `[Legal] Uploading mandatory 'Resignation Acceptance Letter'...`);
                const formData = new FormData();
                // Minimal valid single-page PDF (matches upload middleware's allowed MIME list).
                const MINIMAL_PDF = '%PDF-1.4\n1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj\n2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj\n3 0 obj<</Type/Page/Parent 2 0 R/MediaBox[0 0 300 144]/Contents 4 0 R/Resources<<>>>>endobj\n4 0 obj<</Length 50>>stream\nBT /F1 12 Tf 36 100 Td (Mock Acceptance Letter) Tj ET\nendstream endobj\nxref\n0 5\n0000000000 65535 f \n0000000010 00000 n \n0000000053 00000 n \n0000000100 00000 n \n0000000180 00000 n \ntrailer<</Size 5/Root 1 0 R>>\nstartxref\n260\n%%EOF';
                const blob = new Blob([MINIMAL_PDF], { type: 'application/pdf' });
                formData.append('file', blob, 'Acceptance_Letter.pdf');
                formData.append('documentType', 'Resignation Acceptance Letter');
                formData.append('stage', 'Legal');

                const uploadRes = await fetch(`${BASE_URL}/self-service/resignations/${resignationId}/documents`, {
                    method: 'POST',
                    headers: { 'Authorization': `Bearer ${token}` },
                    body: formData
                });
                const uploadData = await uploadRes.json();
                if (!uploadRes.ok) throw new Error(`Document upload failed: ${JSON.stringify(uploadData)}`);
                log(currentStep, `[Legal] Document uploaded successfully.`);
            }

            const res = await apiRequest(`/self-service/resignations/${resignationId}/approve`, 'PUT', {
                remarks: actor.remarks,
                force: true 
            }, token);
            log(currentStep, `${actor.name} Result: ${res.message || 'SUCCESS'}`);
            currentStep++;
            await delay();
        }

        // --- F&F CLEARANCE LOOP (must match backend FNF_DEPARTMENTS + resignation updateClearance) ---
        // F&F is created with no default line items; this loop is what creates DepartmentClaim / receivable & payable rows.
        // Sends JSON PUT (no file). Backend uses uploadSingleIfMultipart so express.json body is preserved.
        // type: 'Receivable' | 'Payable' (backend normalizes legacy 'Recovery' to Receivable).
        if (!SHOULD_SKIP_CLEARANCES) {
            console.log('[STEP 9] Starting 16-Department F&F Clearance Flow...');
        }
        
        // Re-fetch to ensure we have the F&F ID regardless of start point
        const finalResData = await apiRequest(`/self-service/resignations/${resignationId}`, 'GET', null, adminToken);
        const fnfId = finalResData.resignation.settlement?.id;
        
        if (!fnfId) {
            throw new Error(`F&F Settlement ID not found for Resignation ${resignationId}. Ensure it reached F&F Initiation stage.`);
        }
        
        console.log(`F&F Settlement ID: ${fnfId}`);
        await delay();



        const departments = [
            { name: 'Warranty Department', status: 'Cleared', amount: 0, type: 'Receivable', remarks: 'No pending claims.' },
            { name: 'Accessories Department', status: 'Cleared', amount: 0, type: 'Receivable', remarks: 'Stock returned and verified.' },
            { name: 'Sales Department', status: 'Cleared', amount: 0, type: 'Receivable', remarks: 'Allocations transferred.' },
            { name: 'RTO Department', status: 'Dues', amount: 1500, type: 'Receivable', remarks: 'Pending RTO tax recovery.' },
            { name: 'Service Department', status: 'Cleared', amount: 0, type: 'Receivable', remarks: 'Service tools handed over.' },
            { name: 'Parts Department', status: 'Dues', amount: 45000, type: 'Payable', remarks: 'Parts credit note adjustment.' },
            { name: 'Finance Department', status: 'Dues', amount: 25000, type: 'Receivable', remarks: 'Short-term loan interest.' },
            { name: 'Insurance Department', status: 'Cleared', amount: 0, type: 'Receivable', remarks: 'Policy renewals handled.' },
            { name: 'Inventory Department', status: 'Cleared', amount: 0, type: 'Receivable', remarks: 'Physical inventory reconciled.' },
            { name: 'Marketing Department', status: 'Dues', amount: 5000, type: 'Receivable', remarks: 'Glow-sign board removal cost.' },
            { name: 'HR Department', status: 'Cleared', amount: 0, type: 'Receivable', remarks: 'Dealer staff settlement verified.' },
            { name: 'IT Department', status: 'Dues', amount: 12000, type: 'Receivable', remarks: 'Laptop / DMS hardware dues.' },
            { name: 'Legal Department', status: 'Cleared', amount: 0, type: 'Receivable', remarks: 'Legal NOC issued.' },
            { name: 'Quality Department', status: 'Cleared', amount: 0, type: 'Receivable', remarks: 'Quality audit passed.' },
            { name: 'Logistics Department', status: 'Cleared', amount: 0, type: 'Receivable', remarks: 'Last vehicle transit clear.' },
            { name: 'Customer Relations Department', status: 'Cleared', amount: 0, type: 'Receivable', remarks: 'Customer complaints resolved.' }
        ];

        if (!SHOULD_SKIP_CLEARANCES) {
            for (const dept of departments) {
                log('9.1', `Clearing Dept: ${dept.name} [${dept.status}] - ${dept.remarks}`);
                await apiRequest(`/self-service/resignations/${resignationId}/clearance`, 'PUT', {
                    department: dept.name,
                    status: dept.status,
                    remarks: dept.remarks,
                    amount: dept.amount,
                    type: dept.type
                }, adminToken);
                await delay(100); 
            }
            log(9, 'All 16 Departments Cleared.');
            await delay();
        }

        // --- FINAL FINANCE SETTLEMENT ---
        if (!SHOULD_SKIP_FINAL_SETTLEMENT) {
            console.log('[STEP 10] Finance Finalizing Settlement...');
            const financeToken = await login(EMAILS.FINANCE);
            await apiRequest(`/settlement/fnf/${fnfId}`, 'PUT', {
                status: 'Completed',
                finalSettlementAmount: Number(args.finalSettlementAmount || 415173),
                paymentMode: 'NEFT / Bank Transfer',
                transactionReference: `TXN-${Date.now()}`,
                settlementDate: new Date().toISOString(),
                remarks: 'Settlement completed and verified via automated script.'
            }, financeToken);
            await delay();
        }

        // --- FINAL COMPLETION ---
        console.log('[STEP 11] Verifying Resignation is now COMPLETED (Auto-transitioned)...');
        const finalStatusRes = await apiRequest(`/self-service/resignations/${resignationId}`, 'GET', null, adminToken);
        if (finalStatusRes.resignation.status === 'Completed') {
            log(11, 'Resignation auto-transitioned to Completed successfully.');
        } else {
            console.log(`[STEP 11] FAILED: Current status is ${finalStatusRes.resignation.status}`);
            // Fallback: manually trigger completion if auto-sync failed to keep script running
            await apiRequest(`/self-service/resignations/${resignationId}/approve`, 'PUT', {
                remarks: 'Final resignation completion (Manual Fallback).',
                force: true
            }, adminToken);
        }
        await delay();

        // [FINAL STEP] Verification of deactivation
        console.log(`[FINAL STEP] Verifying Account Deactivation...`);
        
        // Get updated user status
        const userRes = await apiRequest('/admin/users', 'GET', null, adminToken);
        
        // Fetch dealer to get its associated user ID
        const dealerU = userRes.data.find(u => u.email === targetApp.email);

        if (dealerU && (dealerU.status === 'deactivated' || !dealerU.isActive)) {
            console.log(`[VERIFICATION] SUCCESS: Account ${dealerU.email} is deactivated. Status: ${dealerU.status}`);
        } else {
            console.log(`[VERIFICATION] Failed: Account ${targetApp.email} is still active. Status: ${dealerU?.status || 'unknown'}`);
            throw new Error('Automated account deactivation check failed.');
        }

        console.log('--- DEALER RESIGNATION E2E FLOW COMPLETED SUCCESSFULLY ---');

    } catch (error) {
        console.error('Workflow failed:', error.message);
        process.exit(1);
    }
}

run();
