import { useState, useMemo } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faFileImport, faCheck, faSpinner, faTriangleExclamation, faCloudArrowUp, faArrowRight } from '@fortawesome/pro-duotone-svg-icons';
import { Dialog, Modal, ModalOverlay } from '@/components/application/modals/modal';
import { Button } from '@/components/base/buttons/button';
import { Badge } from '@/components/base/badges/badges';
import { Select } from '@/components/base/select/select';
import { DynamicTable } from '@/components/application/table/dynamic-table';
import type { DynamicColumn, DynamicRow } from '@/components/application/table/dynamic-table';
import { FeaturedIcon } from '@/components/foundations/featured-icon/featured-icon';
import { useData } from '@/providers/data-provider';
import { apiClient } from '@/lib/api-client';
import { parseCSV, fuzzyMatchColumns, buildLeadPayload, normalizePhone, LEAD_FIELDS } from '@/lib/csv-utils';
import { cx } from '@/utils/cx';
import type { Campaign } from '@/types/entities';
import type { LeadFieldMapping, CSVRow } from '@/lib/csv-utils';
import type { FC } from 'react';

const FileImportIcon: FC<{ className?: string }> = ({ className }) => (
    <FontAwesomeIcon icon={faFileImport} className={className} />
);

type ImportStep = 'select-campaign' | 'map-columns' | 'preview' | 'importing' | 'done';

const WIZARD_STEPS = [
    { key: 'select-campaign', label: 'Select Campaign', number: 1 },
    { key: 'map-columns', label: 'Upload & Map', number: 2 },
    { key: 'preview', label: 'Preview', number: 3 },
    { key: 'done', label: 'Import', number: 4 },
] as const;

const StepIndicator = ({ currentStep }: { currentStep: ImportStep }) => {
    const activeIndex = currentStep === 'importing'
        ? 3
        : WIZARD_STEPS.findIndex(s => s.key === currentStep);

    return (
        <div className="flex items-center justify-center gap-0 px-6 py-3 border-b border-secondary shrink-0">
            {WIZARD_STEPS.map((step, i) => {
                const isComplete = i < activeIndex;
                const isActive = i === activeIndex;
                const isLast = i === WIZARD_STEPS.length - 1;

                return (
                    <div key={step.key} className="flex items-center">
                        <div className="flex items-center gap-2">
                            <div className={cx(
                                'flex size-7 items-center justify-center rounded-full text-xs font-semibold transition duration-100 ease-linear',
                                isComplete ? 'bg-brand-solid text-white' :
                                isActive ? 'bg-brand-solid text-white ring-4 ring-brand-100' :
                                'bg-secondary text-quaternary',
                            )}>
                                {isComplete ? <FontAwesomeIcon icon={faCheck} className="size-3" /> : step.number}
                            </div>
                            <span className={cx(
                                'text-xs font-medium whitespace-nowrap',
                                isActive ? 'text-brand-secondary' : isComplete ? 'text-primary' : 'text-quaternary',
                            )}>
                                {step.label}
                            </span>
                        </div>
                        {!isLast && (
                            <div className={cx(
                                'mx-3 h-px w-12',
                                i < activeIndex ? 'bg-brand-solid' : 'bg-secondary',
                            )} />
                        )}
                    </div>
                );
            })}
        </div>
    );
};

type ImportResult = {
    created: number;
    linkedToPatient: number;
    skippedDuplicate: number;
    skippedNoPhone: number;
    failed: number;
    total: number;
};

interface LeadImportWizardProps {
    isOpen: boolean;
    onOpenChange: (open: boolean) => void;
}

const PAGE_SIZE = 15;

export const LeadImportWizard = ({ isOpen, onOpenChange }: LeadImportWizardProps) => {
    const { campaigns, leads, patients, refresh } = useData();
    const [step, setStep] = useState<ImportStep>('select-campaign');
    const [selectedCampaign, setSelectedCampaign] = useState<Campaign | null>(null);
    const [csvRows, setCsvRows] = useState<CSVRow[]>([]);
    const [mapping, setMapping] = useState<LeadFieldMapping[]>([]);
    const [result, setResult] = useState<ImportResult | null>(null);
    const [importProgress, setImportProgress] = useState(0);
    const [previewPage, setPreviewPage] = useState(1);

    const activeCampaigns = useMemo(() =>
        campaigns.filter(c => c.campaignStatus === 'ACTIVE' || c.campaignStatus === 'PAUSED'),
        [campaigns],
    );

    const handleClose = () => {
        onOpenChange(false);
        setTimeout(() => {
            setStep('select-campaign');
            setSelectedCampaign(null);
            setCsvRows([]);
            setMapping([]);
            setResult(null);
            setImportProgress(0);
            setPreviewPage(1);
        }, 300);
    };

    const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
        const file = e.target.files?.[0];
        if (!file) return;
        const reader = new FileReader();
        reader.onload = (event) => {
            const text = event.target?.result as string;
            const { rows, headers } = parseCSV(text);
            setCsvRows(rows);
            setMapping(fuzzyMatchColumns(headers));
        };
        reader.readAsText(file);
    };

    const handleMappingChange = (csvHeader: string, leadField: string | null) => {
        setMapping(prev => prev.map(m =>
            m.csvHeader === csvHeader ? { ...m, leadField, label: leadField ? LEAD_FIELDS.find(f => f.field === leadField)?.label ?? '' : '' } : m,
        ));
    };

    // Patient matching
    const rowsWithMatch = useMemo(() => {
        const phoneMapping = mapping.find(m => m.leadField === 'contactPhone');
        if (!phoneMapping || csvRows.length === 0) return [];

        const existingLeadPhones = new Set(
            leads.map(l => normalizePhone(l.contactPhone?.[0]?.number ?? '')).filter(p => p.length === 10),
        );
        const patientByPhone = new Map(
            patients.filter(p => p.phones?.primaryPhoneNumber).map(p => [normalizePhone(p.phones!.primaryPhoneNumber), p]),
        );

        return csvRows.map(row => {
            const rawPhone = row[phoneMapping.csvHeader] ?? '';
            const phone = normalizePhone(rawPhone);
            const matchedPatient = phone.length === 10 ? patientByPhone.get(phone) : null;
            const isDuplicate = phone.length === 10 && existingLeadPhones.has(phone);
            const hasPhone = phone.length === 10;
            return { row, phone, matchedPatient, isDuplicate, hasPhone };
        });
    }, [csvRows, mapping, leads, patients]);

    const phoneIsMapped = mapping.some(m => m.leadField === 'contactPhone');
    const validCount = rowsWithMatch.filter(r => r.hasPhone && !r.isDuplicate).length;
    const duplicateCount = rowsWithMatch.filter(r => r.isDuplicate).length;
    const noPhoneCount = rowsWithMatch.filter(r => !r.hasPhone).length;
    const patientMatchCount = rowsWithMatch.filter(r => r.matchedPatient).length;
    const totalPreviewPages = Math.max(1, Math.ceil(rowsWithMatch.length / PAGE_SIZE));

    const handleImport = async () => {
        if (!selectedCampaign) return;
        setStep('importing');

        const importResult: ImportResult = { created: 0, linkedToPatient: 0, skippedDuplicate: 0, skippedNoPhone: 0, failed: 0, total: rowsWithMatch.length };

        for (let i = 0; i < rowsWithMatch.length; i++) {
            const { row, isDuplicate, hasPhone, matchedPatient } = rowsWithMatch[i];
            if (!hasPhone) { importResult.skippedNoPhone++; setImportProgress(i + 1); continue; }
            if (isDuplicate) { importResult.skippedDuplicate++; setImportProgress(i + 1); continue; }

            const payload = buildLeadPayload(row, mapping, selectedCampaign.id, matchedPatient?.id ?? null, selectedCampaign.platform);
            if (!payload) { importResult.skippedNoPhone++; setImportProgress(i + 1); continue; }

            try {
                await apiClient.graphql(`mutation($data: LeadCreateInput!) { createLead(data: $data) { id } }`, { data: payload }, { silent: true });
                importResult.created++;
                if (matchedPatient) importResult.linkedToPatient++;
            } catch { importResult.failed++; }
            setImportProgress(i + 1);
        }

        setResult(importResult);
        setStep('done');
        refresh();
    };

    // Select dropdown items for mapping
    const mappingOptions = [
        { id: '__skip__', label: '— Skip —' },
        ...LEAD_FIELDS.map(f => ({ id: f.field, label: f.label })),
    ];

    return (
        <ModalOverlay isOpen={isOpen} isDismissable onOpenChange={(open) => { if (!open) handleClose(); }}>
            <Modal className="sm:max-w-5xl">
                <Dialog>
                    {() => (
                        <div className="flex w-full flex-col rounded-xl bg-primary shadow-xl ring-1 ring-secondary overflow-hidden" style={{ height: '80vh', minHeight: '500px' }}>
                            {/* Header */}
                            <div className="flex items-center justify-between px-6 py-4 border-b border-secondary shrink-0">
                                <div className="flex items-center gap-3">
                                    <FeaturedIcon icon={FileImportIcon} color="brand" theme="light" size="sm" />
                                    <div>
                                        <h2 className="text-lg font-semibold text-primary">Import Leads</h2>
                                        <p className="text-xs text-tertiary">
                                            {step === 'select-campaign' && 'Select a campaign to import leads into'}
                                            {step === 'map-columns' && 'Upload CSV and map columns to lead fields'}
                                            {step === 'preview' && `Preview: ${selectedCampaign?.campaignName}`}
                                            {step === 'importing' && 'Importing leads...'}
                                            {step === 'done' && 'Import complete'}
                                        </p>
                                    </div>
                                </div>
                                <button onClick={handleClose} className="text-fg-quaternary hover:text-fg-secondary text-lg">&times;</button>
                            </div>

                            <StepIndicator currentStep={step} />

                            {/* Content */}
                            <div className="flex flex-1 flex-col min-h-0 overflow-hidden">

                                {/* Step 1: Campaign Cards */}
                                {step === 'select-campaign' && (
                                    <div className="flex-1 overflow-y-auto px-6 py-4">
                                        <div className="grid grid-cols-2 gap-3">
                                            {activeCampaigns.length === 0 ? (
                                                <p className="col-span-2 py-12 text-center text-sm text-tertiary">No active campaigns.</p>
                                            ) : activeCampaigns.map(campaign => (
                                                <button
                                                    key={campaign.id}
                                                    onClick={() => { setSelectedCampaign(campaign); setStep('map-columns'); }}
                                                    className={cx(
                                                        'flex flex-col items-start rounded-xl border-2 p-4 text-left transition duration-100 ease-linear hover:border-brand',
                                                        selectedCampaign?.id === campaign.id ? 'border-brand bg-brand-primary' : 'border-secondary',
                                                    )}
                                                >
                                                    <span className="text-sm font-semibold text-primary">{campaign.campaignName ?? 'Untitled'}</span>
                                                    <div className="mt-1 flex items-center gap-2">
                                                        {campaign.platform && <Badge size="sm" color="brand" type="pill-color">{campaign.platform}</Badge>}
                                                        <Badge size="sm" color={campaign.campaignStatus === 'ACTIVE' ? 'success' : 'gray'} type="pill-color">{campaign.campaignStatus}</Badge>
                                                    </div>
                                                    <span className="mt-2 text-xs text-tertiary">{leads.filter(l => l.campaignId === campaign.id).length} leads</span>
                                                </button>
                                            ))}
                                        </div>
                                    </div>
                                )}

                                {/* Step 2: Upload + Column Mapping */}
                                {step === 'map-columns' && (
                                    <div className="flex-1 overflow-y-auto px-6 py-4 space-y-4">
                                        {csvRows.length === 0 ? (
                                            <label className="flex flex-col items-center justify-center rounded-xl border-2 border-dashed border-secondary py-16 cursor-pointer hover:border-brand hover:bg-brand-primary transition duration-100 ease-linear">
                                                <FontAwesomeIcon icon={faCloudArrowUp} className="size-10 text-fg-quaternary mb-3" />
                                                <span className="text-sm font-medium text-secondary">Drop CSV file here or click to browse</span>
                                                <span className="text-xs text-tertiary mt-1">CSV files only, max 5000 rows</span>
                                                <input type="file" accept=".csv" onChange={handleFileUpload} className="hidden" />
                                            </label>
                                        ) : (
                                            <>
                                                <div className="flex items-center justify-between">
                                                    <span className="text-sm font-medium text-primary">{csvRows.length} rows detected — map columns to lead fields:</span>
                                                    {!phoneIsMapped && (
                                                        <div className="flex items-center gap-1.5 text-xs text-error-primary">
                                                            <FontAwesomeIcon icon={faTriangleExclamation} className="size-3" />
                                                            Phone column required
                                                        </div>
                                                    )}
                                                </div>

                                                <div className="grid grid-cols-2 gap-3">
                                                    {mapping.map(m => (
                                                        <div key={m.csvHeader} className="flex items-center gap-3 rounded-lg border border-secondary p-3">
                                                            <div className="min-w-0 flex-1">
                                                                <span className="text-xs font-semibold text-primary block">{m.csvHeader}</span>
                                                                <span className="text-[10px] text-quaternary">CSV column</span>
                                                            </div>
                                                            <FontAwesomeIcon icon={faArrowRight} className="size-3 text-fg-quaternary shrink-0" />
                                                            <div className="w-44 shrink-0">
                                                                <Select
                                                                    size="sm"
                                                                    placeholder="Skip"
                                                                    items={mappingOptions}
                                                                    selectedKey={m.leadField ?? '__skip__'}
                                                                    onSelectionChange={(key) => handleMappingChange(m.csvHeader, key === '__skip__' ? null : String(key))}
                                                                >
                                                                    {(item) => <Select.Item id={item.id}>{item.label}</Select.Item>}
                                                                </Select>
                                                            </div>
                                                        </div>
                                                    ))}
                                                </div>
                                            </>
                                        )}
                                    </div>
                                )}

                                {/* Step 3: Preview Table */}
                                {step === 'preview' && (
                                    <div className="flex flex-1 flex-col min-h-0">
                                        {/* Summary bar */}
                                        <div className="flex shrink-0 items-center gap-4 px-6 py-2 border-b border-secondary text-xs text-tertiary">
                                            <span>{rowsWithMatch.length} rows</span>
                                            <span className="text-success-primary">{validCount} ready</span>
                                            {patientMatchCount > 0 && <span className="text-brand-secondary">{patientMatchCount} existing patients</span>}
                                            {duplicateCount > 0 && <span className="text-warning-primary">{duplicateCount} duplicates</span>}
                                            {noPhoneCount > 0 && <span className="text-error-primary">{noPhoneCount} no phone</span>}
                                        </div>

                                        {/* Table — fills remaining space, header pinned, body scrolls */}
                                        <div className="flex flex-1 flex-col min-h-0 px-4 pt-2">
                                            <DynamicTable<DynamicRow>
                                                columns={[
                                                    ...mapping.filter(m => m.leadField).map(m => ({
                                                        id: m.csvHeader,
                                                        label: LEAD_FIELDS.find(f => f.field === m.leadField)?.label ?? m.csvHeader,
                                                    }) as DynamicColumn),
                                                    { id: '__match__', label: 'Patient Match' },
                                                ]}
                                                rows={rowsWithMatch.slice((previewPage - 1) * PAGE_SIZE, previewPage * PAGE_SIZE).map((item, i) => ({ id: `row-${i}`, ...item }))}
                                                renderCell={(row, columnId) => {
                                                    if (columnId === '__match__') {
                                                        if (row.matchedPatient) return <Badge size="sm" color="success" type="pill-color">{row.matchedPatient.fullName?.firstName ?? 'Patient'}</Badge>;
                                                        if (row.isDuplicate) return <Badge size="sm" color="warning" type="pill-color">Duplicate</Badge>;
                                                        if (!row.hasPhone) return <Badge size="sm" color="error" type="pill-color">No phone</Badge>;
                                                        return <Badge size="sm" color="gray" type="pill-color">New</Badge>;
                                                    }
                                                    return <span className="text-tertiary truncate block max-w-[200px]">{row.row?.[columnId] ?? ''}</span>;
                                                }}
                                                rowClassName={(row) => cx(
                                                    row.isDuplicate && 'bg-warning-primary opacity-60',
                                                    !row.hasPhone && 'bg-error-primary opacity-40',
                                                )}
                                            />
                                        </div>

                                        {/* Pagination — pinned at bottom */}
                                        {totalPreviewPages > 1 && (
                                            <div className="flex shrink-0 items-center justify-between border-t border-secondary px-6 py-2">
                                                <span className="text-xs text-tertiary">
                                                    Page {previewPage} of {totalPreviewPages}
                                                </span>
                                                <div className="flex items-center gap-1">
                                                    <button
                                                        onClick={() => setPreviewPage(Math.max(1, previewPage - 1))}
                                                        disabled={previewPage === 1}
                                                        className="px-2 py-1 text-xs font-medium text-secondary rounded-md hover:bg-primary_hover disabled:text-disabled disabled:cursor-not-allowed"
                                                    >
                                                        Previous
                                                    </button>
                                                    <button
                                                        onClick={() => setPreviewPage(Math.min(totalPreviewPages, previewPage + 1))}
                                                        disabled={previewPage === totalPreviewPages}
                                                        className="px-2 py-1 text-xs font-medium text-secondary rounded-md hover:bg-primary_hover disabled:text-disabled disabled:cursor-not-allowed"
                                                    >
                                                        Next
                                                    </button>
                                                </div>
                                            </div>
                                        )}
                                    </div>
                                )}

                                {/* Step 4a: Importing */}
                                {step === 'importing' && (
                                    <div className="flex flex-1 items-center justify-center">
                                        <div className="flex flex-col items-center">
                                            <FontAwesomeIcon icon={faSpinner} className="size-8 animate-spin text-brand-secondary mb-4" />
                                            <p className="text-sm font-semibold text-primary">Importing leads...</p>
                                            <p className="text-xs text-tertiary mt-1">{importProgress} of {rowsWithMatch.length}</p>
                                            <div className="mt-4 w-64 h-2 rounded-full bg-secondary overflow-hidden">
                                                <div className="h-full rounded-full bg-brand-solid transition-all duration-200" style={{ width: `${(importProgress / rowsWithMatch.length) * 100}%` }} />
                                            </div>
                                        </div>
                                    </div>
                                )}

                                {/* Step 4b: Done */}
                                {step === 'done' && result && (
                                    <div className="flex flex-1 items-center justify-center">
                                        <div className="flex flex-col items-center">
                                            <FeaturedIcon icon={({ className }) => <FontAwesomeIcon icon={faCheck} className={className} />} color="success" theme="light" size="lg" />
                                            <p className="text-lg font-semibold text-primary mt-4">Import Complete</p>
                                            <div className="mt-4 grid grid-cols-2 gap-3 w-64 text-center">
                                                <div className="rounded-lg bg-success-primary p-3">
                                                    <p className="text-xl font-bold text-success-primary">{result.created}</p>
                                                    <p className="text-xs text-tertiary">Created</p>
                                                </div>
                                                <div className="rounded-lg bg-brand-primary p-3">
                                                    <p className="text-xl font-bold text-brand-secondary">{result.linkedToPatient}</p>
                                                    <p className="text-xs text-tertiary">Linked</p>
                                                </div>
                                                {result.skippedDuplicate > 0 && (
                                                    <div className="rounded-lg bg-warning-primary p-3">
                                                        <p className="text-xl font-bold text-warning-primary">{result.skippedDuplicate}</p>
                                                        <p className="text-xs text-tertiary">Duplicates</p>
                                                    </div>
                                                )}
                                                {result.failed > 0 && (
                                                    <div className="rounded-lg bg-error-primary p-3">
                                                        <p className="text-xl font-bold text-error-primary">{result.failed}</p>
                                                        <p className="text-xs text-tertiary">Failed</p>
                                                    </div>
                                                )}
                                            </div>
                                        </div>
                                    </div>
                                )}
                            </div>

                            {/* Footer */}
                            <div className="flex items-center justify-between px-6 py-4 border-t border-secondary shrink-0">
                                {step === 'select-campaign' && (
                                    <Button size="sm" color="secondary" onClick={handleClose}>Cancel</Button>
                                )}
                                {step === 'map-columns' && (
                                    <>
                                        <Button size="sm" color="secondary" onClick={() => { setStep('select-campaign'); setCsvRows([]); setMapping([]); }}>Back</Button>
                                        {csvRows.length > 0 && (
                                            <Button size="sm" color="primary" onClick={() => { setPreviewPage(1); setStep('preview'); }} isDisabled={!phoneIsMapped}>
                                                Preview {validCount} Lead{validCount !== 1 ? 's' : ''}
                                            </Button>
                                        )}
                                    </>
                                )}
                                {step === 'preview' && (
                                    <>
                                        <Button size="sm" color="secondary" onClick={() => setStep('map-columns')}>Back to Mapping</Button>
                                        <Button size="sm" color="primary" onClick={handleImport} isDisabled={validCount === 0}>
                                            Import {validCount} Lead{validCount !== 1 ? 's' : ''}
                                        </Button>
                                    </>
                                )}
                                {step === 'done' && (
                                    <Button size="sm" color="primary" onClick={handleClose} className="ml-auto">Done</Button>
                                )}
                            </div>
                        </div>
                    )}
                </Dialog>
            </Modal>
        </ModalOverlay>
    );
};
