export type CSVRow = Record<string, string>;

// CSV write-side. Quote every value and escape embedded quotes. Prefix
// ="+-@ with a single quote so Excel doesn't interpret them as formulas
// (classic CSV-injection vector on exports opened in spreadsheet apps).
const escapeCsvCell = (raw: unknown): string => {
    const value = raw == null ? '' : String(raw);
    const sanitized = /^[=+\-@]/.test(value) ? `'${value}` : value;
    return `"${sanitized.replace(/"/g, '""')}"`;
};

export const rowsToCsv = (headers: string[], rows: Array<Record<string, unknown>>): string => {
    const lines = [headers.map(escapeCsvCell).join(',')];
    for (const row of rows) {
        lines.push(headers.map((h) => escapeCsvCell(row[h])).join(','));
    }
    return lines.join('\r\n');
};

export const downloadCsv = (filename: string, csv: string): void => {
    // BOM prefix so Excel recognises UTF-8 for non-ASCII names/addresses.
    const blob = new Blob(['\ufeff', csv], { type: 'text/csv;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = filename;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(url);
};


export type CSVParseResult = {
    headers: string[];
    rows: CSVRow[];
};

export const parseCSV = (text: string): CSVParseResult => {
    const lines = text.split(/\r?\n/).filter(line => line.trim());
    if (lines.length === 0) return { headers: [], rows: [] };

    const parseLine = (line: string): string[] => {
        const result: string[] = [];
        let current = '';
        let inQuotes = false;

        for (let i = 0; i < line.length; i++) {
            const char = line[i];
            if (char === '"') {
                if (inQuotes && line[i + 1] === '"') {
                    current += '"';
                    i++;
                } else {
                    inQuotes = !inQuotes;
                }
            } else if (char === ',' && !inQuotes) {
                result.push(current.trim());
                current = '';
            } else {
                current += char;
            }
        }
        result.push(current.trim());
        return result;
    };

    const headers = parseLine(lines[0]);
    const rows = lines.slice(1).map(line => {
        const values = parseLine(line);
        const row: CSVRow = {};
        headers.forEach((header, i) => {
            row[header] = values[i] ?? '';
        });
        return row;
    });

    return { headers, rows };
};

export const normalizePhone = (raw: string): string => {
    const digits = raw.replace(/\D/g, '');
    const stripped = digits.length >= 12 && digits.startsWith('91') ? digits.slice(2) : digits;
    return stripped.slice(-10);
};

export type LeadFieldMapping = {
    csvHeader: string;
    leadField: string | null;
    label: string;
};

const LEAD_FIELDS = [
    { field: 'contactName.firstName', label: 'First Name', patterns: ['first name', 'firstname', 'name', 'patient name', 'patient'] },
    { field: 'contactName.lastName', label: 'Last Name', patterns: ['last name', 'lastname', 'surname'] },
    { field: 'contactPhone', label: 'Phone', patterns: ['phone', 'mobile', 'contact number', 'cell', 'phone number', 'mobile number'] },
    { field: 'contactEmail', label: 'Email', patterns: ['email', 'email address', 'mail'] },
    { field: 'interestedService', label: 'Interested Service', patterns: ['service', 'interested in', 'department', 'specialty', 'interest'] },
    { field: 'priority', label: 'Priority', patterns: ['priority', 'urgency'] },
    { field: 'utmSource', label: 'UTM Source', patterns: ['utm_source', 'utmsource', 'source'] },
    { field: 'utmMedium', label: 'UTM Medium', patterns: ['utm_medium', 'utmmedium', 'medium'] },
    { field: 'utmCampaign', label: 'UTM Campaign', patterns: ['utm_campaign', 'utmcampaign'] },
    { field: 'utmTerm', label: 'UTM Term', patterns: ['utm_term', 'utmterm', 'term'] },
    { field: 'utmContent', label: 'UTM Content', patterns: ['utm_content', 'utmcontent'] },
];

export const fuzzyMatchColumns = (csvHeaders: string[]): LeadFieldMapping[] => {
    const used = new Set<string>();

    return csvHeaders.map(header => {
        const normalized = header.toLowerCase().trim().replace(/[^a-z0-9 ]/g, '');
        let bestMatch: string | null = null;

        for (const field of LEAD_FIELDS) {
            if (used.has(field.field)) continue;
            if (field.patterns.some(p => normalized === p || normalized.includes(p))) {
                bestMatch = field.field;
                used.add(field.field);
                break;
            }
        }

        return {
            csvHeader: header,
            leadField: bestMatch,
            label: bestMatch ? LEAD_FIELDS.find(f => f.field === bestMatch)!.label : '',
        };
    });
};

export const buildLeadPayload = (
    row: CSVRow,
    mapping: LeadFieldMapping[],
    campaignId: string,
    patientId: string | null,
    platform: string | null,
) => {
    const getValue = (field: string): string => {
        const entry = mapping.find(m => m.leadField === field);
        return entry ? (row[entry.csvHeader] ?? '').trim() : '';
    };

    const firstName = getValue('contactName.firstName') || 'Unknown';
    const lastName = getValue('contactName.lastName');
    const phone = normalizePhone(getValue('contactPhone'));

    if (!phone || phone.length < 10) return null;

    const sourceMap: Record<string, string> = {
        FACEBOOK: 'FACEBOOK_AD',
        GOOGLE: 'GOOGLE_AD',
        INSTAGRAM: 'INSTAGRAM',
        MANUAL: 'OTHER',
    };

    return {
        name: `${firstName} ${lastName}`.trim(),
        contactName: { firstName, lastName },
        contactPhone: { primaryPhoneNumber: `+91${phone}` },
        ...(getValue('contactEmail') ? { contactEmail: { primaryEmail: getValue('contactEmail') } } : {}),
        ...(getValue('interestedService') ? { interestedService: getValue('interestedService') } : {}),
        ...(getValue('utmSource') ? { utmSource: getValue('utmSource') } : {}),
        ...(getValue('utmMedium') ? { utmMedium: getValue('utmMedium') } : {}),
        ...(getValue('utmCampaign') ? { utmCampaign: getValue('utmCampaign') } : {}),
        ...(getValue('utmTerm') ? { utmTerm: getValue('utmTerm') } : {}),
        ...(getValue('utmContent') ? { utmContent: getValue('utmContent') } : {}),
        source: sourceMap[platform ?? ''] ?? 'OTHER',
        status: 'NEW',
        campaignId,
        ...(patientId ? { patientId } : {}),
    };
};

export { LEAD_FIELDS };
