/**
 * ROYAL ENFIELD DEALER ONBOARDING - END-TO-END WORKFLOW TRIGGER
 * This script automates the entire journey from Application to LOA.
 */

import fs from 'fs';
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 OTP = '123456';
const STEP_DELAY_MS = Number(args.delayMs || 1000);

// Append timestamp to email to avoid duplicate application error
const timestamp = Date.now();
const PROSPECT_EMAIL = `ramesh_${timestamp}@gmail.com`;

const EMAILS = {
    PROSPECT: PROSPECT_EMAIL,
    RBM_L1: 'manish@royalenfield.com',
    ZM_L1: 'piyush@royalenfield.com',
    DD_LEAD: 'jaya@royalenfield.com',
    ZBH: 'laxmanhalaki814@gmail.com',
    NBH: 'yashwin@royalenfield.com',
    DD_HEAD: 'ganesh@royalenfield.com',
    FDD: 'fdd@royalenfield.com',
    FINANCE: 'finance@royalenfield.com',
    DD_ADMIN: 'lince@royalenfield.com',
    ASM: 'abhishek@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',
    LEGAL: 'legal@royalenfield.com',
    LOGISTICS: 'logistics@royalenfield.com',
    QUALITY: 'quality@royalenfield.com',
    APPAREL: 'apparel@royalenfield.com',
    DMS: 'dms@royalenfield.com'
};

const PROSPECT_PAYLOAD = {
    applicantName: "ramesh",
    email: PROSPECT_EMAIL,
    phone: "8197735918",
    businessType: "Dealership",
    locationType: "Urban",
    district: "South Delhi",
    city: "South Delhi",
    state: "DELHI",
    preferredLocation: "Indiranagar",
    address: "123, 100ft Road",
    pincode: "520038",
    experienceYears: 5,
    investmentCapacity: "2-3 Cr",
    age: 32,
    education: "MBA",
    companyName: "Kumar Automobiles",
    source: "Website",
    existingDealer: "No",
    ownRoyalEnfield: "Yes",
    royalEnfieldModel: "Classic 350",
    description: "Interested in opening a main dealership.",
    panNumber: 'ABCDE1234F',
    gstNumber: '07ABCDE1234F1Z5',
    bankName: 'HDFC Bank',
    accountNumber: '50100223344556',
    ifscCode: 'HDFC0001234',
    accountHolderName: 'Kumar Automobiles Private Limited',
    registeredAddress: '123, Main Road, New Delhi'
};

// State to store IDs between steps
let applicationId = null;
let applicationUUID = null;
let interviewId = null;
let loaRequestId = null;

/** 
 * HELPERS
 */
const delay = (ms = STEP_DELAY_MS) => new Promise(res => setTimeout(res, ms));

const log = (step, msg) => console.log(`[STEP ${step}] ${msg}`);

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) {
        console.error(`\x1b[31mFAIL: ${method} ${endpoint} returned ${response.status}\x1b[0m`);
        console.error(JSON.stringify(data, null, 2));
        process.exit(1);
    }
    return data;
}

async function login(email) {
    if (!login.cache) login.cache = {};
    if (login.cache[email]) return login.cache[email];
    const data = await apiRequest('/auth/login', 'POST', { email, password: PASSWORD });
    login.cache[email] = data.token;
    return login.cache[email]; // Standard login returns token at root
}

async function prospectLogin(phone) {
    await apiRequest('/prospective-login/send-otp', 'POST', { phone });
    const data = await apiRequest('/prospective-login/verify-otp', 'POST', { phone, otp: OTP });
    return data.data.token; // Prospect OTP returns token inside data object
}

async function mockUploadDocument(appId, token, docType) {
    const formData = new FormData();
    const fileBuffer = fs.readFileSync('/home/laxman/Pictures/Screenshots/Screenshot from 2026-05-13 20-23-30.png');
    const blob = new Blob([fileBuffer], { type: 'image/png' });
    formData.append('file', blob, 'screenshot.png');
    formData.append('documentType', docType);

    const headers = { 'Authorization': `Bearer ${token}` };
    const response = await fetch(`${BASE_URL}/onboarding/applications/${appId}/documents`, {
        method: 'POST',
        headers,
        body: formData
    });
    if (!response.ok) {
        throw new Error(`Upload Failed: ${response.status}`);
    }
    return response.json();
}

async function getApplicationStatus(appId, token) {
    const res = await apiRequest(`/onboarding/applications/${appId}`, 'GET', null, token);
    return res?.data?.overallStatus || res?.data?.status || 'Unknown';
}

async function ensureMandatoryCodeGenFields(appId, token) {
    const details = await apiRequest(`/onboarding/applications/${appId}`, 'GET', null, token);
    const app = details?.data || {};

    const fallbackFields = {
        panNumber: app.panNumber || 'ABCDE1234F',
        gstNumber: app.gstNumber || '07ABCDE1234F1Z5',
        bankName: app.bankName || 'HDFC Bank',
        accountNumber: app.accountNumber || '50100223344556',
        ifscCode: app.ifscCode || 'HDFC0001234',
        accountHolderName: app.accountHolderName || 'Kumar Automobiles Private Limited',
        registeredAddress: app.registeredAddress || '123, Main Road, New Delhi'
    };

    await apiRequest(`/onboarding/applications/${appId}`, 'PUT', fallbackFields, token);
}

/**
 * MAIN WORKFLOW
 */
async function triggerWorkflow() {
    console.log('--- STARTING DEALER ONBOARDING E2E FLOW ---\n');

    if (args.applicationId) {
        applicationId = args.applicationId;
        applicationUUID = args.applicationId;
        log(1, `Resuming with existing application: ${applicationUUID}`);
    } else {
        // 1. PUBLIC APPLY
        log(1, 'Public Prospect Application Submission...');
        const appResponse = await apiRequest('/onboarding/apply', 'POST', PROSPECT_PAYLOAD);
        applicationId = appResponse.data.applicationId;
        applicationUUID = appResponse.data.id;
        log(1, `Application Created: ${applicationId} (UUID: ${applicationUUID})`);
        await delay();
    }

    // 2. ADMIN SHORTLIST
    log(2, 'Admin Login & Shortlisting...');
    const adminToken = await login(EMAILS.DD_ADMIN);
    // Find the ASM to assign (just picking the first user with role DD-ASM if we could, 
    // but for now assigning to DD-Lead for testing)
    const users = await apiRequest('/admin/users', 'GET', null, adminToken);
    const ddLead = users.data.find(u => u.email === EMAILS.ASM);

    await apiRequest('/onboarding/applications/shortlist', 'POST', {
        applicationIds: [applicationId],
        assignedTo: [ddLead.id],
        remarks: 'Shortlisted for evaluation'
    }, adminToken);
    log(2, 'Application Shortlisted successfully.');
    await delay();

    // 3. SKIP QUESTIONNAIRE FOR TESTING STABILITY
    log(3, 'Skipping Questionnaire stage for test stability...');
    await delay();

    // 4. LEVEL-1 INTERVIEW
    log(4, 'ASM Scheduling Level 1 Interview...');
    const leadToken = await login(EMAILS.DD_LEAD);
    const rbmUser = users.data.find(u => u.email === EMAILS.RBM_L1);
    const zmUser = users.data.find(u => u.email === EMAILS.ZM_L1);
    const zbhUser = users.data.find(u => u.email === EMAILS.ZBH) || users.data[2];

    const intvResponse = await apiRequest('/assessment/interviews', 'POST', {
        applicationId: applicationUUID,
        level: 1,
        scheduledAt: new Date(Date.now() + 86400000).toISOString(),
        type: 'In-Person',
        location: 'Zonal Office',
        participants: [rbmUser.id, zmUser.id]
    }, leadToken);
    interviewId = intvResponse.data.id;
    log(4, `Level 1 Interview Scheduled (ID: ${interviewId})`);
    await delay();

    // FEEDBACK RBM
    log(4.1, 'RBM Giving Feedback...');
    const rbmToken = await login(EMAILS.RBM_L1);
    await apiRequest('/assessment/kt-matrix', 'POST', {
        interviewId,
        criteriaScores: [{ criterionName: 'Business Acumen', score: 8.5, maxScore: 10, weightage: 100 }],
        feedback: 'Strong business acumen.',
        recommendation: 'Selected'
    }, rbmToken);

    // FEEDBACK ZM
    log(4.2, 'ZM Giving Feedback...');
    const zmToken = await login(EMAILS.ZM_L1);
    await apiRequest('/assessment/kt-matrix', 'POST', {
        interviewId,
        criteriaScores: [{ criterionName: 'Vision', score: 9.0, maxScore: 10, weightage: 100 }],
        feedback: 'Good vision for RE brand.',
        recommendation: 'Selected'
    }, zmToken);

    // ZM DECISION (Rajesh Khanna)
    log(4.3, 'ZM Finalizing Level 1 Decision...');
    await apiRequest('/assessment/decision', 'POST', {
        interviewId,
        decision: 'Approved',
        remarks: 'Cleared Level 1'
    }, zmToken);
    log(4, 'Level 1 Complete.');
    await delay();

    // 5. LEVEL-2 INTERVIEW
    log(5, 'Scheduling Level 2 Interview...');

    const intv2Response = await apiRequest('/assessment/interviews', 'POST', {
        applicationId: applicationUUID,
        level: 2,
        scheduledAt: new Date(Date.now() + 172800000).toISOString(),
        type: 'Online',
        location: 'Teams',
        participants: [ddLead.id, zbhUser.id]
    }, leadToken);
    const interviewId2 = intv2Response.data.id;

    log(5.1, 'DD-Lead Giving Feedback...');
    await apiRequest('/assessment/level2-feedback', 'POST', {
        interviewId: interviewId2,
        overallScore: 9.5,
        feedbackItems: [
            { type: 'Strategic Vision', comments: 'Excellent strategic planning.' },
            { type: 'Management Capabilities', comments: 'Strong team leadership.' },
            { type: 'Operational Understanding', comments: 'Knows the local market well.' }
        ],
        recommendation: 'Selected'
    }, leadToken);

    log(5.15, 'ZBH Giving Feedback...');
    const zbhToken = await login(zbhUser.email);
    await apiRequest('/assessment/level2-feedback', 'POST', {
        interviewId: interviewId2,
        overallScore: 9.0,
        feedbackItems: [
            { type: 'Strategic Vision', comments: 'Good alignment with brand.' },
            { type: 'Key Strengths', comments: 'Great location proposed.' },
            { type: 'Areas of Concern', comments: 'None at this time.' }
        ],
        recommendation: 'Selected'
    }, zbhToken);

    log(5.2, 'DD-Lead Finalizing Level 2 Decision...');
    await apiRequest('/assessment/decision', 'POST', {
        interviewId: interviewId2,
        decision: 'Approved',
        remarks: 'Cleared Level 2'
    }, leadToken);
    log(5, 'Level 2 Complete.');
    await delay();

    // 6. LEVEL-3 INTERVIEW
    log(6, 'Scheduling Level 3 Interview...');
    const headUser = users.data.find(u => u.email === EMAILS.DD_HEAD);
    const nbhUser = users.data.find(u => u.email === EMAILS.NBH);

    const intv3Response = await apiRequest('/assessment/interviews', 'POST', {
        applicationId: applicationUUID,
        level: 3,
        scheduledAt: new Date(Date.now() + 259200000).toISOString(),
        type: 'In-Person',
        location: 'HO',
        participants: [headUser.id, nbhUser.id]
    }, leadToken);
    const interviewId3 = intv3Response.data.id;

    log(6.1, 'NBH Giving Feedback...');
    const nbhToken = await login(EMAILS.NBH);
    await apiRequest('/assessment/level2-feedback', 'POST', {
        interviewId: interviewId3,
        overallScore: 10,
        feedbackItems: [
            { type: 'Business Vision & Strategy', comments: 'Highly recommended for this market.' },
            { type: 'Leadership & Decision Making', comments: 'Shows great potential.' }
        ],
        recommendation: 'Selected'
    }, nbhToken);

    log(6.15, 'DD-Head Giving Feedback...');
    const headToken = await login(EMAILS.DD_HEAD);
    await apiRequest('/assessment/level2-feedback', 'POST', {
        interviewId: interviewId3,
        overallScore: 9.5,
        feedbackItems: [
            { type: 'Operational & Financial Readiness', comments: 'Financially sound.' },
            { type: 'Brand Alignment', comments: 'Understands Royal Enfield ethos perfectly.' }
        ],
        recommendation: 'Selected'
    }, headToken);

    log(6.2, 'Head Finalizing Level 3 Decision...');
    await apiRequest('/assessment/decision', 'POST', {
        interviewId: interviewId3,
        decision: 'Approved',
        remarks: 'Cleared Level 3. Moving to FDD.'
    }, headToken);
    log(6, 'Level 3 Complete. Stage is now FDD Verification.');
    await delay();

    // 6.3 FDD ASSIGNMENT
    log(6.3, 'Admin Assigning Application to FDD Agency...');
    const fddUser = users.data.find(u => u.email === EMAILS.FDD);
    await apiRequest('/fdd/assign', 'POST', {
        applicationId: applicationUUID,
        assignedToAgency: fddUser.id
    }, adminToken);
    log(6.3, 'FDD Agency assigned successfully.');
    await delay();

    // 7. FDD MILESTONE
    log(7, 'FDD Agency Discovery & Report Upload...');
    const fddToken = await login(EMAILS.FDD);

    // FETCH ASSIGNMENT ID
    const assignmentRes = await apiRequest(`/fdd/${applicationUUID}`, 'GET', null, fddToken);
    const assignmentId = assignmentRes.data.id;
    log(7, `Found Assignment ID: ${assignmentId}`);

    await apiRequest('/fdd/report', 'POST', {
        assignmentId,
        findings: 'Finance records clean.',
        recommendation: 'Approved'
    }, fddToken);

    log(7.1, 'Admin Approving FDD Final Stage...');
    await apiRequest('/assessment/stage-decision', 'POST', {
        applicationId: applicationUUID,
        stageCode: 'FDD_VERIFICATION',
        decision: 'Approved',
        remarks: 'FDD documents verified.'
    }, adminToken);
    log(7, 'FDD Milestone Complete.');
    await delay();

    log(7.4, 'Uploading mandatory pre-LOI evidence documents (CIBIL / Site / Bank / GST / PAN)...');
    const preLoiDocs = ['CIBIL Report', 'Proposed Site City Map', 'Bank Statement', 'GST Certificate', 'PAN Card'];
    for (const doc of preLoiDocs) {
        await mockUploadDocument(applicationUUID, adminToken, doc);
    }
    await delay(1000);

    // 7.5 LOI APPROVAL (multi-approver: DD-Head + NBH)
    log(7.5, 'Requesting LOI and collecting required approvals...');
    const loiRes = await apiRequest('/loi/request', 'POST', { applicationId: applicationUUID }, adminToken);
    const loiRequestId = loiRes.data.id;
    log(7.5, `LOI Request created (ID: ${loiRequestId})`);

    // DD-Head Approval
    await apiRequest(`/loi/request/${loiRequestId}/approve`, 'POST', {
        action: 'Approved',
        remarks: 'DD-Head authorization for LOI'
    }, headToken);

    // NBH Approval — final approver flips overallStatus to "Security Details"
    // (LOI Approved → moves into the Security Deposit corridor before LOI Issue).
    await apiRequest(`/loi/request/${loiRequestId}/approve`, 'POST', {
        action: 'Approved',
        remarks: 'NBH authorization for LOI'
    }, nbhToken);

    log(7.5, 'LOI fully approved. Backend transitioned to Security Deposit corridor.');
    await delay();

    // 8. SECURITY DEPOSIT — Finance verifies advance payment.
    // Backend keeps app at "Security Details" (no auto-jump to LOI Issued) — admin must
    // (a) upload LOI documents and (b) explicitly transition. See loa.controller.ts.
    log(8, 'Finance Verifying SECURITY_DEPOSIT (₹5L advance)...');
    const financeToken = await login(EMAILS.FINANCE);
    await apiRequest('/loa/security-deposit', 'POST', {
        applicationId: applicationUUID,
        amount: 500000,
        paymentReference: `PAY-SD-${Date.now()}`,
        depositType: 'SECURITY_DEPOSIT',
        status: 'Verified'
    }, financeToken);
    log(8, 'Security Deposit Verified.');
    await delay();

    // 8.5 LOI DOCUMENTS COLLECTION
    // Per business rule (and the new UI "LOI Documents" stage), the dealer-side LOI artefacts
    // must be uploaded BEFORE the admin transitions the application to "LOI Issued".
    log(8.5, 'Uploading LOI Documents (Letter of Intent + Signed LOI) prior to LOI Issuance...');
    const loiDocs = ['Letter of Intent', 'Signed LOI'];
    for (const doc of loiDocs) {
        await mockUploadDocument(applicationUUID, adminToken, doc);
    }
    log(8.5, 'LOI Documents uploaded. Ready for LOI Issued transition.');
    await delay();

    // 9. LOI ISSUE — explicit admin transition + LOI document generation.
    let statusBeforeCodeGen = await getApplicationStatus(applicationUUID, adminToken);
    log(9, `Current status before LOI Issued transition: ${statusBeforeCodeGen}`);

    log(9, 'Ensuring mandatory PAN/GST/Bank fields are populated...');
    await ensureMandatoryCodeGenFields(applicationUUID, adminToken);
    await delay(300);

    if (statusBeforeCodeGen === 'Security Deposit' || statusBeforeCodeGen === 'Security Details') {
        log(9, 'Applying admin transition: Security Deposit -> LOI Issued...');
        await apiRequest(`/onboarding/applications/${applicationUUID}/status`, 'PUT', {
            status: 'LOI Issued',
            stage: 'LOI',
            reason: 'LOI documents collected and verified. Releasing LOI Issued milestone.'
        }, adminToken);
        await delay();
        statusBeforeCodeGen = await getApplicationStatus(applicationUUID, adminToken);
        log(9, `Status after admin transition: ${statusBeforeCodeGen}`);
    }

    // generateDocument bridges LOI Issued -> Dealer Code Generation (loi.controller.ts:459).
    // Route is POST /loi/request/:requestId/generate — requestId goes in the URL, not the body.
    log(9, 'Generating final LOI document (bridges to Dealer Code Generation)...');
    await apiRequest(`/loi/request/${loiRequestId}/generate`, 'POST', {}, adminToken);
    await delay();
    statusBeforeCodeGen = await getApplicationStatus(applicationUUID, adminToken);
    log(9, `Status after LOI generateDocument: ${statusBeforeCodeGen}`);

    if (statusBeforeCodeGen !== 'LOI Issued' && statusBeforeCodeGen !== 'Dealer Code Generation') {
        throw new Error(`Cannot generate codes: expected LOI Issued/Dealer Code Generation, got ${statusBeforeCodeGen}`);
    }

    log(9, 'Admin Generating SAP Dealer Codes...');
    await apiRequest(`/onboarding/applications/${applicationUUID}/generate-codes`, 'POST', {}, adminToken);
    log(9, 'Dealer Codes Generated.');
    await delay();

    // 10. FIRST FILL (POST CODE-GENERATION)
    log(10, 'Finance Verifying FIRST FILL (₹15L)...');
    await apiRequest('/loa/security-deposit', 'POST', {
        applicationId: applicationUUID,
        amount: 1500000,
        paymentReference: `PAY-FF-${Date.now()}`,
        depositType: 'FIRST_FILL',
        status: 'Verified'
    }, financeToken);
    log(10, 'First Fill Verified.');
    await delay();

    // 11. ADMIN UPDATING STATUTORY & BANK DETAILS
    log(11, 'Admin Updating Statutory & Bank Details for LOA Approval Gate...');
    await apiRequest(`/onboarding/applications/${applicationUUID}`, 'PUT', {
        accountHolderName: 'Ramesh Automobiles Private Limited',
        panNumber: 'ABCDE1234F',
        gstNumber: '07ABCDE1234F1Z5',
        bankName: 'HDFC Bank',
        accountNumber: '50100223344556',
        ifscCode: 'HDFC0001234'
    }, adminToken);
    log(11, 'Statutory & Bank details updated.');
    await delay();

    // 12. FINAL LOA APPROVAL
    log(12, 'NBH & Head Approving Final LOA...');
    const loaRes = await apiRequest('/loa/request', 'POST', { applicationId: applicationUUID }, headToken);
    const finalLoaRequestId = loaRes.data.id;

    await apiRequest(`/loa/request/${finalLoaRequestId}/approve`, 'POST', {
        action: 'Approved',
        remarks: 'Head Authorization (Level 1)'
    }, headToken);

    await apiRequest(`/loa/request/${finalLoaRequestId}/approve`, 'POST', {
        action: 'Approved',
        remarks: 'NBH Approval (Level 2)'
    }, nbhToken);
    log(12, 'LOA Fully Approved.');
    await delay();

    // 13. EOR (EVIDENCE OF READINESS) CHECKLIST VERIFICATION
    log(13, 'Admin Initializing EOR Checklist (100% Readiness Requirement)...');
    const eorInit = await apiRequest('/eor', 'POST', { applicationId: applicationUUID }, adminToken);
    const checklistId = eorInit.data.id;
    log(13, `EOR Checklist Created (ID: ${checklistId})`);

    log(13.1, 'Auditor Verifying all 12 mandatory EOR items as COMPLIANT...');
    const eorItems = [
        { 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' }
    ];

    for (const item of eorItems) {
        process.stdout.write(`.`);
        await apiRequest(`/eor/item/${checklistId}`, 'POST', {
            ...item,
            isCompliant: true,
            remarks: 'Verified by Auditor - Compliant'
        }, adminToken);
    }
    console.log('\n[STEP 13.1] All EOR items marked as compliant.');

    log(13.2, 'Auditor Submitting Final EOR Audit...');
    await apiRequest(`/eor/audit/${checklistId}`, 'POST', {
        status: 'Completed',
        overallComments: 'Dealer is 100% ready for inauguration. All infra and statutory items verified.'
    }, adminToken);

    const finalAppStatus = await apiRequest(`/onboarding/applications/${applicationUUID}`, 'GET', null, adminToken);
    log(13.2, `Application Status after EOR: ${finalAppStatus.data.overallStatus}`);
    await delay();

    // 14. FINAL ONBOARDING
    log(14, 'Admin Finalizing Dealer Onboarding...');
    await apiRequest('/dealers', 'POST', { applicationId: applicationUUID }, adminToken);
    await delay();

    // 15. VERIFICATION
    log(15, 'Verifying Dealer Record Creation...');
    const dealerRes = await apiRequest(`/dealers/application/${applicationUUID}`, 'GET', null, adminToken);
    if (!dealerRes.success || !dealerRes.data) {
        throw new Error('Verification Failed: Dealer record not found after onboarding.');
    }
    log(15, `Dealer Found: ${dealerRes.data.legalName} (${dealerRes.data.id})`);

    log(15.1, 'Verifying User Account Role Update...');
    const userRes = await apiRequest(`/admin/users`, 'GET', null, adminToken);
    const dealerUser = userRes.data.find(u => u.email === PROSPECT_EMAIL);
    if (!dealerUser || dealerUser.roleCode !== 'Dealer') {
        throw new Error(`Verification Failed: User role not updated to 'Dealer'. Current role: ${dealerUser?.roleCode}`);
    }
    log(15.1, `User role confirmed: ${dealerUser.roleCode}`);

    log(15.2, '--- WORKFLOW COMPLETED SUCCESSFULLY! ---');
    log(15.2, `The application ${applicationId} is now at 'ONBOARDED' status and Dealer profile is active.`);
}

/**
 * START
 */
triggerWorkflow().catch(err => {
    console.error('\x1b[31mCRITICAL FAILURE during workflow execution:\x1b[0m');
    console.error(err);
    process.exit(1);
});
