import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
import {
  LineChart,
  Line,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
  ResponsiveContainer,
} from 'recharts';
import {
  PiggyBank,
  Upload,
  X,
  TrendingUp,
  Calendar,
  Percent,
  Banknote,
  FileText,
  Loader2,
  CheckCircle2,
  AlertTriangle,
} from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Badge } from '@/components/ui/badge';
import { Separator } from '@/components/ui/separator';
import {
  uploadPensionPDFs,
  getPensionFundSummary,
  getPensionSnapshots,
  type PensionSnapshot,
  type PensionUploadResult,
} from '@/api';
import PensionManualEntryModal from '@/components/PensionManualEntryModal';
import { ClipboardPaste } from 'lucide-react';

// ─── Types ────────────────────────────────────────────────────────────────────

type FundKey = 'FCL' | 'ROP' | 'VOL';

interface FundDef {
  key: FundKey;
  name: string;
  fullName: string;
  color: string;
  startBalance: number;
  monthlyContribution: number;
  annualRate: number;
  isDividend: boolean;
  withdrawalRule: string;
  defaultTargetAge: number;
}

interface ProjectionState {
  contribution: number;
  rate: number;
  targetAge: number;
}

interface ChartDataPoint extends Record<FundKey, number> {
  month: string;
}

interface TooltipEntry {
  name: string;
  value: number;
  color: string;
}

// ─── Constants ────────────────────────────────────────────────────────────────

const CURRENT_AGE = 30;

const FUND_KEYS: FundKey[] = ['FCL', 'ROP', 'VOL'];

const FUNDS_DEFAULT: Record<FundKey, FundDef> = {
  FCL: {
    key: 'FCL',
    name: 'FCL',
    fullName: 'Fondo de Capitalización Laboral',
    color: '#3b82f6',
    startBalance: 650_468,
    monthlyContribution: 150_000,
    annualRate: 7.5,
    isDividend: false,
    withdrawalRule: 'Retirable cada 5 años o al cambio de empleo',
    defaultTargetAge: 35,
  },
  ROP: {
    key: 'ROP',
    name: 'ROP',
    fullName: 'Régimen Obligatorio de Pensiones',
    color: '#10b981',
    startBalance: 18_684_765,
    monthlyContribution: 120_000,
    annualRate: 6.0,
    isDividend: false,
    withdrawalRule: 'Retirable a los 65 años',
    defaultTargetAge: 65,
  },
  VOL: {
    key: 'VOL',
    name: 'VOL',
    fullName: 'Fondo Voluntario',
    color: '#f43f5e',
    startBalance: 2_500_381,
    monthlyContribution: 400_000,
    annualRate: 8.0,
    isDividend: false,
    withdrawalRule: 'Accesible a los 57 años',
    defaultTargetAge: 57,
  },
};

const MONTH_NAMES_ES = [
  'Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun',
  'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic',
];

// ─── Utilities ────────────────────────────────────────────────────────────────

const formatCRC = (amount: number): string =>
  new Intl.NumberFormat('es-CR', {
    style: 'currency',
    currency: 'CRC',
    maximumFractionDigits: 0,
  }).format(amount);

function buildChartFromSnapshots(snapshots: PensionSnapshot[]): ChartDataPoint[] {
  // Group by period_end month key (YYYY-MM)
  const byMonth = new Map<string, Record<string, number>>();

  for (const snap of snapshots) {
    const d = new Date(snap.period_end);
    const key = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`;
    if (!byMonth.has(key)) byMonth.set(key, {});
    const entry = byMonth.get(key)!;
    const fund = snap.fund as FundKey;
    // Keep the latest saldo_final per fund per month
    entry[fund] = Math.round(snap.saldo_final);
  }

  // Sort chronologically and take last 12
  const sortedKeys = Array.from(byMonth.keys()).sort();
  const last12 = sortedKeys.slice(-12);

  return last12.map((key) => {
    const [yearStr, monthStr] = key.split('-');
    const monthIdx = parseInt(monthStr, 10) - 1;
    const yearShort = yearStr.slice(2);
    const label = `${MONTH_NAMES_ES[monthIdx]} ${yearShort}`;
    const values = byMonth.get(key)!;
    return {
      month: label,
      FCL: values.FCL ?? 0,
      ROP: values.ROP ?? 0,
      VOL: values.VOL ?? 0,
    } as ChartDataPoint;
  });
}

function calcProjection(
  currentBalance: number,
  monthlyContribution: number,
  annualRate: number,
  targetAge: number,
  isDividend: boolean,
): number {
  const years = Math.max(0, targetAge - CURRENT_AGE);
  if (years === 0) return currentBalance;

  if (isDividend) {
    let balance = currentBalance;
    const rate = annualRate / 100;
    for (let y = 0; y < years; y++) {
      balance = balance + monthlyContribution * 12 + balance * rate;
    }
    return balance;
  }

  const r = annualRate / 100 / 12;
  const n = years * 12;
  if (r === 0) return currentBalance + monthlyContribution * n;
  return (
    currentBalance * Math.pow(1 + r, n) +
    monthlyContribution * ((Math.pow(1 + r, n) - 1) / r)
  );
}

/** Merge API snapshots into the default fund definitions. */
function applySnapshots(
  snapshots: PensionSnapshot[],
): Record<FundKey, FundDef> {
  const funds = { ...FUNDS_DEFAULT };
  for (const snap of snapshots) {
    const key = snap.fund as FundKey;
    if (key in funds) {
      funds[key] = { ...funds[key], startBalance: Math.round(snap.saldo_final) };
    }
  }
  return funds;
}

// ─── Chart Tooltip ────────────────────────────────────────────────────────────

function ChartTooltipContent({
  active,
  payload,
  label,
}: {
  active?: boolean;
  payload?: TooltipEntry[];
  label?: string;
}) {
  if (!active || !payload?.length) return null;
  return (
    <div className="bg-popover border border-border rounded-lg p-3 shadow-lg text-sm min-w-[220px]">
      <p className="font-semibold mb-2 text-foreground">{label}</p>
      {payload.map((entry) => (
        <div key={entry.name} className="flex items-center justify-between gap-4 py-0.5">
          <span className="flex items-center gap-1.5">
            <span
              className="w-2.5 h-2.5 rounded-full flex-shrink-0"
              style={{ background: entry.color }}
            />
            <span className="text-muted-foreground">{entry.name}</span>
          </span>
          <span data-sensitive className="font-mono font-medium text-foreground">{formatCRC(entry.value)}</span>
        </div>
      ))}
    </div>
  );
}

// ─── Main Component ───────────────────────────────────────────────────────────

export default function Pensions() {
  const [fundSummary, setFundSummary] = useState<PensionSnapshot[]>([]);
  const [allSnapshots, setAllSnapshots] = useState<PensionSnapshot[]>([]);
  const [visibleFunds, setVisibleFunds] = useState<Set<FundKey>>(new Set(FUND_KEYS));
  const [projections, setProjections] = useState<Record<FundKey, ProjectionState>>({
    FCL: { contribution: 150_000, rate: 7.5, targetAge: 35 },
    ROP: { contribution: 120_000, rate: 6.0, targetAge: 65 },
    VOL: { contribution: 400_000, rate: 8.0, targetAge: 57 },
  });
  const [uploadedFiles, setUploadedFiles] = useState<File[]>([]);
  const [isDragging, setIsDragging] = useState(false);
  const [isUploading, setIsUploading] = useState(false);
  const [uploadResult, setUploadResult] = useState<PensionUploadResult | null>(null);
  const [showManualEntry, setShowManualEntry] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const loadData = useCallback(async () => {
    try {
      const [summaryRes, snapshotsRes] = await Promise.all([
        getPensionFundSummary(),
        getPensionSnapshots(),
      ]);
      setFundSummary(summaryRes.data);
      setAllSnapshots(snapshotsRes.data);
    } catch {
      // API not available or no data yet — use defaults
    }
  }, []);

  useEffect(() => {
    loadData();
  }, [loadData]);

  const FUNDS = useMemo(() => applySnapshots(fundSummary), [fundSummary]);

  // Build a map of fund -> latest snapshot for rendimientos display
  const snapshotByFund = useMemo(() => {
    const map: Partial<Record<FundKey, PensionSnapshot>> = {};
    for (const snap of fundSummary) {
      map[snap.fund as FundKey] = snap;
    }
    return map;
  }, [fundSummary]);

  const chartData = useMemo(() => buildChartFromSnapshots(allSnapshots), [allSnapshots]);

  const chartDateRange = useMemo(() => {
    if (chartData.length < 2) return '';
    return `${chartData[0].month} — ${chartData[chartData.length - 1].month}`;
  }, [chartData]);

  const roiEarned = useMemo(() => {
    return FUND_KEYS.reduce<Record<FundKey, number>>((acc, key) => {
      const snap = snapshotByFund[key];
      if (snap) {
        // Use real rendimientos from the API
        acc[key] = Math.round(snap.rendimientos);
      } else {
        // Fallback: approximate from chart data
        const fund = FUNDS[key];
        const len = chartData.length;
        if (len >= 2 && fund.isDividend) {
          acc[key] = Math.max(0, Math.round(
            chartData[len - 1][key] - chartData[len - 2][key] - fund.monthlyContribution,
          ));
        } else if (len > 0) {
          const activeMonths = chartData.filter((d) => d[key] > 0).length;
          acc[key] = Math.round(fund.startBalance * (fund.annualRate / 100) * (activeMonths / 12));
        } else {
          acc[key] = 0;
        }
      }
      return acc;
    }, {} as Record<FundKey, number>);
  }, [FUNDS, chartData, snapshotByFund]);

  const toggleFund = (key: FundKey) => {
    setVisibleFunds((prev) => {
      const next = new Set(prev);
      if (next.has(key)) {
        if (next.size > 1) next.delete(key);
      } else {
        next.add(key);
      }
      return next;
    });
  };

  const updateProjection = (key: FundKey, field: keyof ProjectionState, value: string) => {
    const num = parseFloat(value);
    setProjections((prev) => ({
      ...prev,
      [key]: { ...prev[key], [field]: isNaN(num) ? 0 : num },
    }));
  };

  const handleFiles = useCallback((files: FileList | null) => {
    if (!files) return;
    const pdfs = Array.from(files).filter((f) => f.type === 'application/pdf');
    setUploadedFiles((prev) => [...prev, ...pdfs]);
    setUploadResult(null);
  }, []);

  const handleUpload = async () => {
    if (uploadedFiles.length === 0) return;
    setIsUploading(true);
    setUploadResult(null);
    try {
      const { data } = await uploadPensionPDFs(uploadedFiles);
      setUploadResult(data);
      setUploadedFiles([]);
      // Refresh fund summary with new data
      await loadData();
    } catch (err) {
      setUploadResult({
        imported: 0,
        updated: 0,
        duplicates: 0,
        errors: [err instanceof Error ? err.message : 'Error al subir archivos'],
        snapshots: [],
      });
    } finally {
      setIsUploading(false);
    }
  };

  const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    setIsDragging(true);
  };

  const handleDragLeave = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    setIsDragging(false);
  };

  const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    setIsDragging(false);
    handleFiles(e.dataTransfer.files);
  };

  const removeFile = (index: number) => {
    setUploadedFiles((prev) => prev.filter((_, i) => i !== index));
  };

  const formatFileSize = (bytes: number): string => {
    if (bytes < 1024) return `${bytes} B`;
    if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
    return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
  };

  return (
    <div className="space-y-8">
      {/* ── Page Header ─────────────────────────────────────────────────── */}
      <div className="flex items-center gap-3">
        <div className="w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center">
          <PiggyBank className="w-5 h-5 text-primary" />
        </div>
        <div>
          <h1 className="text-2xl font-bold font-heading">Pensiones</h1>
          <p className="text-sm text-muted-foreground">
            Seguimiento de aportes, rendimientos y proyecciones
          </p>
        </div>
      </div>

      {/* ── Section 1: Fund Overview Cards ──────────────────────────────── */}
      <section className="space-y-3">
        <h2 className="text-base font-semibold font-heading flex items-center gap-2 text-muted-foreground uppercase tracking-wider">
          <Banknote className="w-4 h-4" />
          Fondos
        </h2>
        <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-4">
          {FUND_KEYS.map((key) => {
            const fund = FUNDS[key];
            const snap = snapshotByFund[key];
            return (
              <Card
                key={key}
                className="border-l-4 overflow-hidden"
                style={{ borderLeftColor: fund.color }}
              >
                <CardContent className="p-4 space-y-3">
                  <div>
                    <div className="flex items-center justify-between gap-1">
                      <span className="font-bold text-base" style={{ color: fund.color }}>
                        {fund.name}
                      </span>
                      <Badge variant={fund.isDividend ? 'secondary' : 'outline'} className="text-xs">
                        {fund.isDividend ? 'Dividendos' : 'Interés'}
                      </Badge>
                    </div>
                    <p className="text-xs text-muted-foreground leading-tight mt-0.5">
                      {fund.fullName}
                    </p>
                  </div>

                  <div>
                    <p className="text-xs text-muted-foreground uppercase tracking-wider font-medium">
                      Balance actual
                    </p>
                    <p data-sensitive className="text-xl font-bold font-mono mt-0.5 leading-tight">
                      {formatCRC(fund.startBalance)}
                    </p>
                    {snap && (
                      <p className="text-xs text-muted-foreground mt-0.5">
                        al {new Date(snap.period_end).toLocaleDateString('es-CR')}
                      </p>
                    )}
                  </div>

                  <Separator />

                  {snap ? (
                    <div className="space-y-1.5 text-xs">
                      <div className="flex justify-between">
                        <span className="text-muted-foreground">Aportes</span>
                        <span data-sensitive className="font-mono font-medium">
                          {formatCRC(snap.aportes)}
                        </span>
                      </div>
                      <div className="flex justify-between">
                        <span className="text-muted-foreground">Rendimientos</span>
                        <span data-sensitive className="font-mono font-medium text-emerald-500">
                          {formatCRC(snap.rendimientos)}
                        </span>
                      </div>
                      <div className="flex justify-between">
                        <span className="text-muted-foreground">Comisión</span>
                        <span data-sensitive className="font-mono font-medium text-destructive">
                          {formatCRC(snap.comision)}
                        </span>
                      </div>
                    </div>
                  ) : (
                    <div className="space-y-1.5 text-xs">
                      <div className="flex justify-between">
                        <span className="text-muted-foreground">Aporte mensual</span>
                        <span data-sensitive className="font-mono font-medium">
                          {formatCRC(fund.monthlyContribution)}
                        </span>
                      </div>
                      <div className="flex justify-between">
                        <span className="text-muted-foreground">Tasa anual</span>
                        <span className="font-mono font-medium">{fund.annualRate}%</span>
                      </div>
                    </div>
                  )}

                  <div className="flex items-start gap-1.5 text-xs text-muted-foreground bg-muted/50 rounded-md p-2">
                    <Calendar className="w-3 h-3 flex-shrink-0 mt-0.5" />
                    <span>{fund.withdrawalRule}</span>
                  </div>
                </CardContent>
              </Card>
            );
          })}
        </div>
      </section>

      {/* ── Section 2: Growth Chart ──────────────────────────────────────── */}
      <section className="space-y-3">
        <h2 className="text-base font-semibold font-heading flex items-center gap-2 text-muted-foreground uppercase tracking-wider">
          <TrendingUp className="w-4 h-4" />
          Evolución del Balance{chartDateRange && ` (${chartDateRange})`}
        </h2>
        <Card>
          <CardContent className="p-4 space-y-4">
            <div className="flex flex-wrap gap-2">
              {FUND_KEYS.map((key) => {
                const fund = FUNDS[key];
                const active = visibleFunds.has(key);
                return (
                  <button
                    key={key}
                    onClick={() => toggleFund(key)}
                    className="flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-medium transition-all border cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
                    style={{
                      borderColor: fund.color,
                      background: active ? fund.color + '22' : 'transparent',
                      color: active ? fund.color : 'var(--muted-foreground)',
                    }}
                  >
                    <span
                      className="w-2 h-2 rounded-full"
                      style={{ background: active ? fund.color : 'var(--muted-foreground)' }}
                    />
                    {fund.name}
                  </button>
                );
              })}
            </div>

            <ResponsiveContainer width="100%" height={320}>
              <LineChart data={chartData} margin={{ top: 4, right: 8, left: 8, bottom: 4 }}>
                <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" />
                <XAxis
                  dataKey="month"
                  tick={{ fontSize: 11, fill: 'var(--muted-foreground)' }}
                  axisLine={{ stroke: 'var(--border)' }}
                  tickLine={false}
                />
                <YAxis
                  tickFormatter={(v: number) => `${(v / 1_000_000).toFixed(1)}M`}
                  tick={{ fontSize: 11, fill: 'var(--muted-foreground)' }}
                  axisLine={false}
                  tickLine={false}
                  width={52}
                />
                <Tooltip content={<ChartTooltipContent />} />
                <Legend
                  formatter={(value) => (
                    <span style={{ fontSize: 12, color: 'var(--foreground)' }}>{value}</span>
                  )}
                />
                {FUND_KEYS.map((key) =>
                  visibleFunds.has(key) ? (
                    <Line
                      key={key}
                      type="monotone"
                      dataKey={key}
                      name={key}
                      stroke={FUNDS[key].color}
                      strokeWidth={2}
                      dot={false}
                      activeDot={{ r: 4 }}
                    />
                  ) : null,
                )}
              </LineChart>
            </ResponsiveContainer>
          </CardContent>
        </Card>
      </section>

      {/* ── Section 3: ROI Summary ───────────────────────────────────────── */}
      <section className="space-y-3">
        <h2 className="text-base font-semibold font-heading flex items-center gap-2 text-muted-foreground uppercase tracking-wider">
          <Percent className="w-4 h-4" />
          Rendimiento — Último Periodo
        </h2>
        <div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3">
          {FUND_KEYS.map((key) => {
            const fund = FUNDS[key];
            const snap = snapshotByFund[key];
            const earned = roiEarned[key];
            return (
              <Card key={key}>
                <CardContent className="p-4">
                  <div className="flex items-center gap-1.5 mb-2">
                    <span
                      className="w-2.5 h-2.5 rounded-full flex-shrink-0"
                      style={{ background: fund.color }}
                    />
                    <span className="font-bold text-sm">{fund.name}</span>
                  </div>
                  {snap ? (
                    <p className="text-xs text-muted-foreground mb-1">
                      {new Date(snap.period_start).toLocaleDateString('es-CR', { month: 'short', year: '2-digit' })}
                      {' — '}
                      {new Date(snap.period_end).toLocaleDateString('es-CR', { month: 'short', year: '2-digit' })}
                    </p>
                  ) : (
                    <p className="text-xs text-muted-foreground mb-1">
                      {fund.isDividend ? `Dividendos ${fund.annualRate}%` : `${fund.annualRate}% anual`}
                    </p>
                  )}
                  <p data-sensitive className="text-lg font-bold font-mono" style={{ color: fund.color }}>
                    {earned >= 0 ? '+' : ''}{formatCRC(earned)}
                  </p>
                  <p className="text-xs text-muted-foreground">en rendimientos</p>
                </CardContent>
              </Card>
            );
          })}
        </div>
      </section>

      {/* ── Section 4: Projections ───────────────────────────────────────── */}
      <section className="space-y-3">
        <h2 className="text-base font-semibold font-heading flex items-center gap-2 text-muted-foreground uppercase tracking-wider">
          <TrendingUp className="w-4 h-4" />
          Proyecciones
        </h2>
        <p className="text-sm text-muted-foreground">
          Basado en edad actual de {CURRENT_AGE} años. Edita los campos para simular escenarios.
        </p>
        <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-4">
          {FUND_KEYS.map((key) => {
            const fund = FUNDS[key];
            const proj = projections[key];
            const projected = calcProjection(
              fund.startBalance,
              proj.contribution,
              proj.rate,
              proj.targetAge,
              fund.isDividend,
            );
            const years = Math.max(0, proj.targetAge - CURRENT_AGE);
            return (
              <Card key={key} className="border-l-4" style={{ borderLeftColor: fund.color }}>
                <CardHeader className="pb-2 pt-4 px-4">
                  <CardTitle className="text-sm font-bold" style={{ color: fund.color }}>
                    {fund.name}
                  </CardTitle>
                </CardHeader>
                <CardContent className="px-4 pb-4 space-y-3">
                  <div className="space-y-2">
                    <div>
                      <Label className="text-xs text-muted-foreground">Aporte mensual (CRC)</Label>
                      <Input
                        type="number"
                        value={proj.contribution}
                        onChange={(e) => updateProjection(key, 'contribution', e.target.value)}
                        className="h-8 text-sm font-mono mt-1"
                      />
                    </div>
                    <div>
                      <Label className="text-xs text-muted-foreground">
                        {fund.isDividend ? 'Tasa dividendo (%)' : 'Tasa anual (%)'}
                      </Label>
                      <Input
                        type="number"
                        step="0.1"
                        value={proj.rate}
                        onChange={(e) => updateProjection(key, 'rate', e.target.value)}
                        className="h-8 text-sm font-mono mt-1"
                      />
                    </div>
                    <div>
                      <Label className="text-xs text-muted-foreground">Edad objetivo</Label>
                      <Input
                        type="number"
                        value={proj.targetAge}
                        onChange={(e) => updateProjection(key, 'targetAge', e.target.value)}
                        className="h-8 text-sm font-mono mt-1"
                      />
                    </div>
                  </div>

                  <Separator />

                  <div className="text-center space-y-0.5">
                    <p className="text-xs text-muted-foreground">
                      Valor en {years} {years === 1 ? 'año' : 'años'}
                    </p>
                    <p
                      data-sensitive
                      className="text-lg font-bold font-mono leading-tight"
                      style={{ color: fund.color }}
                    >
                      {formatCRC(Math.round(projected))}
                    </p>
                  </div>
                </CardContent>
              </Card>
            );
          })}
        </div>
      </section>

      {/* ── Manual Entry Modal ──────────────────────────────────────────── */}
      {showManualEntry && (
        <PensionManualEntryModal
          onClose={() => setShowManualEntry(false)}
          onImported={loadData}
        />
      )}

      {/* ── Section 5: PDF Upload ────────────────────────────────────────── */}
      <section className="space-y-3">
        <div className="flex items-center justify-between">
          <h2 className="text-base font-semibold font-heading flex items-center gap-2 text-muted-foreground uppercase tracking-wider">
            <FileText className="w-4 h-4" />
            Estados de Cuenta
          </h2>
          <Button
            variant="outline"
            size="sm"
            onClick={() => setShowManualEntry(true)}
            className="gap-1.5"
          >
            <ClipboardPaste className="w-3.5 h-3.5" />
            Ingresar manualmente
          </Button>
        </div>
        <Card>
          <CardContent className="p-6 space-y-4">
            {/* Drop zone */}
            <div
              onDragOver={handleDragOver}
              onDragLeave={handleDragLeave}
              onDrop={handleDrop}
              onClick={() => fileInputRef.current?.click()}
              role="button"
              tabIndex={0}
              onKeyDown={(e) => e.key === 'Enter' && fileInputRef.current?.click()}
              aria-label="Seleccionar archivos PDF"
              className={[
                'border-2 border-dashed rounded-lg p-8',
                'flex flex-col items-center justify-center gap-3',
                'cursor-pointer transition-colors select-none',
                'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
                isDragging
                  ? 'border-primary bg-primary/5'
                  : 'border-border hover:border-primary/50 hover:bg-muted/30',
              ].join(' ')}
            >
              <Upload
                className={`w-8 h-8 ${isDragging ? 'text-primary' : 'text-muted-foreground'}`}
              />
              <div className="text-center">
                <p className="text-sm font-medium">
                  {isDragging
                    ? 'Suelta los archivos aquí'
                    : 'Arrastra PDFs aquí o toca para seleccionar'}
                </p>
                <p className="text-xs text-muted-foreground mt-1">
                  Solo archivos PDF · Múltiples archivos soportados
                </p>
              </div>
            </div>

            <input
              ref={fileInputRef}
              type="file"
              accept="application/pdf"
              multiple
              className="hidden"
              onChange={(e) => handleFiles(e.target.files)}
            />

            {/* File list */}
            {uploadedFiles.length > 0 && (
              <div className="space-y-2">
                <p className="text-sm text-muted-foreground font-medium">
                  {uploadedFiles.length}{' '}
                  {uploadedFiles.length === 1 ? 'archivo en cola' : 'archivos en cola'}
                </p>
                <div className="space-y-1.5">
                  {uploadedFiles.map((file, i) => (
                    <div
                      key={i}
                      className="flex items-center justify-between gap-3 p-2.5 rounded-lg bg-muted/50 border border-border"
                    >
                      <div className="flex items-center gap-2.5 min-w-0">
                        <FileText className="w-4 h-4 text-muted-foreground flex-shrink-0" />
                        <div className="min-w-0">
                          <p className="text-sm font-medium truncate">{file.name}</p>
                          <p className="text-xs text-muted-foreground">{formatFileSize(file.size)}</p>
                        </div>
                      </div>
                      <button
                        onClick={() => removeFile(i)}
                        className="flex-shrink-0 p-1 rounded hover:bg-destructive/10 hover:text-destructive transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
                        aria-label={`Eliminar ${file.name}`}
                      >
                        <X className="w-3.5 h-3.5" />
                      </button>
                    </div>
                  ))}
                </div>
              </div>
            )}

            {/* Submit */}
            <Button
              onClick={handleUpload}
              disabled={uploadedFiles.length === 0 || isUploading}
              className="w-full"
            >
              {isUploading ? (
                <Loader2 className="w-4 h-4 mr-2 animate-spin" />
              ) : (
                <Upload className="w-4 h-4 mr-2" />
              )}
              {isUploading ? 'Procesando...' : 'Subir PDFs'}
            </Button>

            {/* Upload result */}
            {uploadResult && (
              <div className={[
                'rounded-lg border p-4 space-y-2',
                uploadResult.errors.length > 0 && uploadResult.imported === 0
                  ? 'border-destructive/50 bg-destructive/5'
                  : 'border-emerald-500/50 bg-emerald-500/5',
              ].join(' ')}>
                <div className="flex items-center gap-2">
                  {(uploadResult.imported > 0 || uploadResult.updated > 0) ? (
                    <CheckCircle2 className="w-4 h-4 text-emerald-500" />
                  ) : (
                    <AlertTriangle className="w-4 h-4 text-amber-500" />
                  )}
                  <span className="text-sm font-medium">
                    {uploadResult.imported > 0 && `${uploadResult.imported} ${uploadResult.imported === 1 ? 'extracto importado' : 'extractos importados'}`}
                    {uploadResult.imported > 0 && uploadResult.updated > 0 && ' · '}
                    {uploadResult.updated > 0 && `${uploadResult.updated} actualizado(s)`}
                    {uploadResult.imported === 0 && uploadResult.updated === 0 && 'Ningún extracto nuevo importado'}
                  </span>
                </div>
                {uploadResult.duplicates > 0 && (
                  <p className="text-xs text-muted-foreground">
                    {uploadResult.duplicates} {uploadResult.duplicates === 1 ? 'duplicado omitido' : 'duplicados omitidos'}
                  </p>
                )}
                {uploadResult.errors.map((err, i) => (
                  <p key={i} className="text-xs text-destructive">{err}</p>
                ))}
                {uploadResult.snapshots.length > 0 && (
                  <div className="space-y-1 pt-1">
                    {uploadResult.snapshots.map((snap) => (
                      <div key={snap.id} className="flex items-center justify-between text-xs">
                        <span className="text-muted-foreground">
                          {snap.fund} · {new Date(snap.period_start).toLocaleDateString('es-CR', { month: 'short', year: '2-digit' })}
                          {' — '}
                          {new Date(snap.period_end).toLocaleDateString('es-CR', { month: 'short', year: '2-digit' })}
                        </span>
                        <span data-sensitive className="font-mono font-medium">{formatCRC(snap.saldo_final)}</span>
                      </div>
                    ))}
                  </div>
                )}
              </div>
            )}
          </CardContent>
        </Card>
      </section>
    </div>
  );
}
