'use client';

import { useState, useEffect, type ComponentType } from 'react';
import { toast } from 'sonner';
import { CheckCircle2, Circle, Loader2, AlertTriangle, CalendarDays } from 'lucide-react';
import { api } from '@/api';
import { cn, fmt, fmtDate, errMessage } from '@/lib/utils';
import type { Dollars } from '@/lib/money';
import { Button } from '@/components/ui/button';
import {
  Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription,
} from '@/components/ui/dialog';

interface StatusMeta {
  label: string | null;
  className: string;
  icon: ComponentType<{ className?: string }> | null;
}

interface Candidate {
  id: number | string;
  status?: string;
  payee?: string | null;
  paid_date?: string | null;
  amount: Dollars;
  matched_bill_name?: string | null;
}

const STATUS_META = {
  unmatched:         { label: 'Unmatched',      className: 'text-muted-foreground',                  icon: null },
  matched_this_bill: { label: 'Already linked', className: 'text-emerald-600 dark:text-emerald-400', icon: CheckCircle2 },
  matched_other_bill:{ label: null,             className: 'text-amber-600 dark:text-amber-400',     icon: AlertTriangle },
  payment_exists:    { label: 'Payment exists', className: 'text-emerald-600 dark:text-emerald-400', icon: CheckCircle2 },
} satisfies Record<string, StatusMeta>;

function StatusChip({ candidate }: { candidate: Candidate }) {
  const meta: StatusMeta = STATUS_META[candidate.status as keyof typeof STATUS_META] ?? STATUS_META.unmatched;
  const Icon = meta.icon;
  const label = candidate.status === 'matched_other_bill'
    ? `Matched to ${candidate.matched_bill_name || 'another bill'}`
    : meta.label;
  if (!label) return null;
  return (
    <span className={cn('text-[10px] font-medium', meta.className)}>
      {Icon && <Icon className="inline h-3 w-3 mr-0.5 -mt-px" />}
      {label}
    </span>
  );
}

// ── Main dialog ───────────────────────────────────────────────────────────────

interface BillHistoricalImportDialogProps {
  billId: number;
  billName: string;
  open: boolean;
  onClose: () => void;
  onImported?: (result: { imported?: number }) => void;
}

export default function BillHistoricalImportDialog({ billId, billName, open, onClose, onImported }: BillHistoricalImportDialogProps) {
  const [step,       setStep]       = useState<'choice' | 'pick'>('choice');
  const [candidates, setCandidates] = useState<Candidate[]>([]);
  const [loading,    setLoading]    = useState(true);
  const [selected,   setSelected]   = useState<Set<number | string>>(new Set());
  const [importing,  setImporting]  = useState(false);

  // Load candidates whenever the dialog opens
  useEffect(() => {
    if (!open || !billId) return;
    setStep('choice');
    setSelected(new Set());
    setLoading(true);
    api.merchantRuleCandidates(billId)
      .then(raw => {
        const data = raw as { candidates?: Candidate[] };
        // Pre-select importable candidates (not already a payment for this bill)
        const importableList = (data.candidates || []).filter(c => c.status !== 'payment_exists' && c.status !== 'matched_this_bill');
        setCandidates(data.candidates || []);
        setSelected(new Set(importableList.map(c => c.id)));
      })
      .catch(() => setCandidates([]))
      .finally(() => setLoading(false));
  }, [open, billId]);

  const importable = candidates.filter(c => c.status !== 'payment_exists' && c.status !== 'matched_this_bill');
  const alreadyDone = candidates.filter(c => c.status === 'payment_exists' || c.status === 'matched_this_bill');

  async function doImport(ids: (number | string)[]) {
    if (ids.length === 0) { onClose(); return; }
    setImporting(true);
    try {
      const result = await api.importHistoricalPayments(billId, ids) as { imported?: number };
      toast.success(`${result.imported} payment${result.imported === 1 ? '' : 's'} imported for ${billName}`);
      onImported?.(result);
      onClose();
    } catch (err) {
      toast.error(errMessage(err, 'Import failed'));
    } finally {
      setImporting(false);
    }
  }

  function toggleAll(checked: boolean) {
    setSelected(checked ? new Set(importable.map(c => c.id)) : new Set());
  }

  function toggle(id: number | string) {
    setSelected(prev => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  }

  const allSelected = importable.length > 0 && importable.every(c => selected.has(c.id));

  // ── Choice step ──────────────────────────────────────────────────────────────
  if (step === 'choice') {
    return (
      <Dialog open={open} onOpenChange={v => { if (!v) onClose(); }}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>
              {!loading && importable.length === 0 && alreadyDone.length === 0
                ? 'No past payments found'
                : !loading && importable.length === 0
                ? 'Already up to date'
                : 'Import past payments'}
            </DialogTitle>
            <DialogDescription>
              {loading
                ? 'Searching your bank history…'
                : importable.length === 0 && alreadyDone.length > 0
                  ? `All matching transactions for ${billName} are already linked — nothing left to import.`
                  : importable.length === 0
                  ? `No past bank transactions found matching ${billName}.`
                  : `Found ${importable.length} past transaction${importable.length === 1 ? '' : 's'} matching ${billName}. What would you like to do?`}
            </DialogDescription>
          </DialogHeader>

          {loading && (
            <div className="flex items-center justify-center py-8">
              <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
            </div>
          )}

          {!loading && importable.length > 0 && (
            <div className="space-y-2.5">
              {/* Populate all */}
              <button
                type="button"
                onClick={() => doImport(importable.map(c => c.id))}
                disabled={importing}
                className="w-full rounded-xl border border-primary/30 bg-primary/5 p-3.5 text-left transition-colors hover:bg-primary/10 disabled:opacity-50"
              >
                <p className="text-sm font-semibold">Import all {importable.length} payments</p>
                <p className="mt-0.5 text-xs text-muted-foreground">
                  Treat your bank as the source of truth — import every matching transaction as a payment.
                </p>
              </button>

              {/* Pick one by one */}
              <button
                type="button"
                onClick={() => setStep('pick')}
                disabled={importing}
                className="w-full rounded-xl border border-border/60 bg-muted/20 p-3.5 text-left transition-colors hover:bg-muted/40 disabled:opacity-50"
              >
                <p className="text-sm font-semibold">Choose which ones</p>
                <p className="mt-0.5 text-xs text-muted-foreground">
                  Review the list and select exactly which transactions to import.
                </p>
              </button>

              {/* Skip */}
              <button
                type="button"
                onClick={onClose}
                disabled={importing}
                className="w-full rounded-xl border border-border/60 bg-background p-3.5 text-left transition-colors hover:bg-muted/20 disabled:opacity-50"
              >
                <p className="text-sm font-semibold">Skip — future only</p>
                <p className="mt-0.5 text-xs text-muted-foreground">
                  Only import new transactions going forward. Past history stays as-is.
                </p>
              </button>
            </div>
          )}

          {!loading && importable.length === 0 && alreadyDone.length > 0 && (
            <p className="text-sm text-muted-foreground">
              All matching transactions are already linked or have payments. Nothing to import.
            </p>
          )}

          {importing && (
            <div className="flex items-center gap-2 text-sm text-muted-foreground">
              <Loader2 className="h-4 w-4 animate-spin" />
              Importing…
            </div>
          )}

          {(!loading || importing) && (
            <DialogFooter>
              <Button variant="ghost" onClick={onClose} disabled={importing}>Cancel</Button>
            </DialogFooter>
          )}
        </DialogContent>
      </Dialog>
    );
  }

  // ── Pick step ────────────────────────────────────────────────────────────────
  return (
    <Dialog open={open} onOpenChange={v => { if (!v) onClose(); }}>
      <DialogContent className="sm:max-w-lg">
        <DialogHeader>
          <DialogTitle>Choose transactions to import</DialogTitle>
          <DialogDescription>
            Select which past transactions to import as payments for {billName}.
          </DialogDescription>
        </DialogHeader>

        {/* Select all toggle */}
        <div className="flex items-center justify-between border-b border-border/50 pb-2">
          <button
            type="button"
            onClick={() => toggleAll(!allSelected)}
            className="flex items-center gap-2 text-xs font-medium text-muted-foreground hover:text-foreground transition-colors"
          >
            {allSelected
              ? <CheckCircle2 className="h-4 w-4 text-primary" />
              : <Circle className="h-4 w-4" />}
            {allSelected ? 'Deselect all' : 'Select all'}
          </button>
          <span className="text-xs text-muted-foreground">{selected.size} selected</span>
        </div>

        {/* Transaction list */}
        <div className="max-h-64 overflow-y-auto space-y-1">
          {importable.map(c => (
            <button
              key={c.id}
              type="button"
              onClick={() => toggle(c.id)}
              className={cn(
                'w-full flex items-center gap-3 rounded-lg border px-3 py-2.5 text-left transition-colors',
                selected.has(c.id)
                  ? 'border-primary/30 bg-primary/5'
                  : 'border-border/50 bg-background hover:bg-muted/30',
              )}
            >
              {selected.has(c.id)
                ? <CheckCircle2 className="h-4 w-4 shrink-0 text-primary" />
                : <Circle className="h-4 w-4 shrink-0 text-muted-foreground" />}
              <div className="min-w-0 flex-1">
                <p className="truncate text-sm font-medium">{c.payee}</p>
                <div className="flex items-center gap-2 mt-0.5">
                  <span className="text-xs text-muted-foreground flex items-center gap-1">
                    <CalendarDays className="h-3 w-3" />{fmtDate(c.paid_date)}
                  </span>
                  <StatusChip candidate={c} />
                </div>
              </div>
              <span className="shrink-0 font-mono text-sm font-semibold tabular-nums">
                {fmt(c.amount)}
              </span>
            </button>
          ))}

          {/* Already-done items (dimmed, informational) */}
          {alreadyDone.length > 0 && (
            <div className="pt-2 border-t border-border/40">
              <p className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground/60 px-1 mb-1">
                Already handled
              </p>
              {alreadyDone.map(c => (
                <div key={c.id} className="flex items-center gap-3 rounded-lg border border-border/30 bg-muted/10 px-3 py-2 opacity-50">
                  <CheckCircle2 className="h-4 w-4 shrink-0 text-emerald-500" />
                  <div className="min-w-0 flex-1">
                    <p className="truncate text-sm">{c.payee}</p>
                    <StatusChip candidate={c} />
                  </div>
                  <span className="shrink-0 font-mono text-sm tabular-nums">{fmt(c.amount)}</span>
                </div>
              ))}
            </div>
          )}
        </div>

        <DialogFooter className="gap-2">
          <Button variant="ghost" onClick={() => setStep('choice')} disabled={importing}>Back</Button>
          <Button
            onClick={() => doImport([...selected])}
            disabled={importing || selected.size === 0}
          >
            {importing
              ? <><Loader2 className="h-3.5 w-3.5 animate-spin mr-1.5" />Importing…</>
              : `Import ${selected.size} payment${selected.size === 1 ? '' : 's'}`}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
