import { useState, useEffect, useCallback, useRef, Suspense, lazy, type ComponentType, type ReactNode } from 'react';
import { useSearchParams } from 'react-router-dom';
import { toast } from 'sonner';
import { motion, AnimatePresence, useReducedMotion } from 'framer-motion';
import {
  Landmark, ArrowRightLeft, Upload, DatabaseBackup,
  FileSpreadsheet, FileText, FlaskConical, Download, RotateCcw, History, ShieldAlert,
} from 'lucide-react';
import { api } from '@/api';
import { errMessage } from '@/lib/utils';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import ConnectionHero from '@/components/data/ConnectionHero';
import DataNav, { type DataNavSection } from '@/components/data/DataNav';
import BankSyncSection from '@/components/data/BankSyncSection';
import BillRulesManager from '@/components/BillRulesManager';
import ImportTransactionCsvSection from '@/components/data/ImportTransactionCsvSection';
import ImportOfxSection from '@/components/data/ImportOfxSection';
import TransactionMatchingSection from '@/components/data/TransactionMatchingSection';
import SeedDemoDataSection from '@/components/data/SeedDemoDataSection';
import DownloadMyDataSection from '@/components/data/DownloadMyDataSection';
import ImportHistorySection, { type ImportHistoryRow } from '@/components/data/ImportHistorySection';
import EraseDataSection from '@/components/data/EraseDataSection';

// Heavy panes (XLSX parsing / SQLite restore) — code-split, loaded on demand.
const ImportSpreadsheetSection = lazy(() => import('@/components/data/ImportSpreadsheetSection'));
const ImportMyDataSection = lazy(() => import('@/components/data/ImportMyDataSection'));

interface Conn {
  id: number | string;
  name?: string;
  provider?: string;
  status?: string;
  last_error?: string | null;
  last_sync_at?: string | null;
}

interface Section {
  id: string;
  label: string;
  description: string;
  icon: ComponentType<{ className?: string }>;
}

const SECTIONS: Section[] = [
  { id: 'bank-sync',    label: 'Bank sync',        description: 'Connect & sync your bank', icon: Landmark },
  { id: 'transactions', label: 'Transactions',     description: 'Review & match',           icon: ArrowRightLeft },
  { id: 'import',       label: 'Import',           description: 'Bring in existing data',   icon: Upload },
  { id: 'export',       label: 'Export & backups', description: 'Download & restore',       icon: DatabaseBackup },
];
const SECTION_IDS = SECTIONS.map(s => s.id);
const DEFAULT_SECTION = SECTIONS[0]!.id;
const SECTION_KEY = 'billtracker:data.section';
const LEGACY_KEY = 'billtracker:data.activeTab'; // old 3-tab key → migrate

function storedSection(): string | null {
  if (typeof window === 'undefined') return null;
  const s = window.localStorage.getItem(SECTION_KEY);
  return s && SECTION_IDS.includes(s) ? s : null;
}

function PaneSkeleton() {
  return (
    <div className="surface p-6">
      <div className="h-5 w-40 animate-pulse rounded bg-muted/50" />
      <div className="mt-3 h-24 animate-pulse rounded bg-muted/30" />
    </div>
  );
}

export default function DataPage() {
  const [searchParams, setSearchParams] = useSearchParams();
  const [history, setHistory] = useState<ImportHistoryRow[] | null>(null);
  const [historyLoading, setHistoryLoading] = useState(true);
  const [transactionRefreshKey, setTransactionRefreshKey] = useState(0);
  const [simplefinConn, setSimplefinConn] = useState<Conn | null>(null);
  const [syncEnabled, setSyncEnabled] = useState(true);
  const [hasConnections, setHasConnections] = useState(false);
  const [syncLoading, setSyncLoading] = useState(true);
  const [syncError, setSyncError] = useState(false);
  const [unmatchedCount, setUnmatchedCount] = useState(0);
  const [txnTotal, setTxnTotal] = useState<number | null>(null);
  const reduceMotion = useReducedMotion();
  const paneRef = useRef<HTMLDivElement>(null);
  const firstRender = useRef(true);

  // Active section: URL ?section= is source of truth → localStorage → default.
  const urlSection = searchParams.get('section');
  const activeSection = (urlSection && SECTION_IDS.includes(urlSection)) ? urlSection : (storedSection() || DEFAULT_SECTION);

  const goTo = useCallback((id: string) => {
    if (!SECTION_IDS.includes(id)) return;
    window.localStorage.setItem(SECTION_KEY, id);
    setSearchParams(prev => {
      const p = new URLSearchParams(prev);
      p.set('section', id);
      return p;
    });
  }, [setSearchParams]);

  // Reflect the resolved section into the URL once, so refresh/back-button work
  // (and migrate the old 3-tab key). Runs only when the URL lacks a valid section.
  useEffect(() => {
    if (urlSection && SECTION_IDS.includes(urlSection)) return;
    const legacy = window.localStorage.getItem(LEGACY_KEY);
    const migrated = legacy ? ({ sync: 'bank-sync', import: 'import', export: 'export' } as Record<string, string>)[legacy] : undefined;
    const target = storedSection() || migrated || DEFAULT_SECTION;
    setSearchParams(prev => {
      const p = new URLSearchParams(prev);
      p.set('section', target);
      return p;
    }, { replace: true });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Move focus to the pane on section change (keyboard/SR), but not on first load.
  useEffect(() => {
    if (firstRender.current) { firstRender.current = false; return; }
    paneRef.current?.focus?.();
  }, [activeSection]);

  const loadHistory = useCallback(async () => {
    setHistoryLoading(true);
    try {
      const res = await api.importHistory() as { history?: ImportHistoryRow[] };
      setHistory(res.history ?? []);
    } catch (err) {
      setHistory([]);
      toast.error(errMessage(err, 'Failed to load import history.'));
    } finally {
      setHistoryLoading(false);
    }
  }, []);

  const loadSimplefinSummary = useCallback(async () => {
    setSyncLoading(true);
    setSyncError(false);
    try {
      const [status, sources] = await Promise.all([
        api.simplefinStatus() as Promise<{ enabled?: boolean; has_connections?: boolean }>,
        api.dataSources({ type: 'provider_sync' }),
      ]);
      setSyncEnabled(Boolean(status.enabled));
      setHasConnections(Boolean(status.has_connections));
      const conns = Array.isArray(sources) ? (sources as Conn[]).filter(s => s.provider === 'simplefin') : [];
      setSimplefinConn(conns[0] || null);
    } catch {
      setSyncError(true);
      setSimplefinConn(null);
    } finally {
      setSyncLoading(false);
    }
  }, []);

  // Cheap "N to review" + transaction count (summary is aggregate, so limit:1 is enough).
  const loadTxnStats = useCallback(async () => {
    try {
      const data = await api.bankTransactionsLedger({ limit: 1 }) as { summary?: { unmatched?: number; total?: number } };
      setUnmatchedCount(data?.summary?.unmatched || 0);
      setTxnTotal(data?.summary?.total ?? null);
    } catch {
      setUnmatchedCount(0);
    }
  }, []);

  useEffect(() => { loadHistory(); loadSimplefinSummary(); }, [loadHistory, loadSimplefinSummary]);
  useEffect(() => { loadTxnStats(); }, [loadTxnStats, transactionRefreshKey]);

  const handleTransactionImportComplete = useCallback(() => {
    loadHistory();
    setTransactionRefreshKey(k => k + 1);
  }, [loadHistory]);

  // BankSyncSection reports connect/sync/disconnect changes.
  const handleConnectionChange = useCallback((conn: Conn | null) => {
    setSimplefinConn(conn || null);
    setHasConnections(Boolean(conn));
    setSyncLoading(false);
    setTransactionRefreshKey(k => k + 1);
  }, []);

  const handleSynced = useCallback(() => {
    loadSimplefinSummary();
    setTransactionRefreshKey(k => k + 1);
  }, [loadSimplefinSummary]);

  const handleErased = useCallback(() => {
    loadHistory();
    loadSimplefinSummary();
    setTransactionRefreshKey(k => k + 1);
  }, [loadHistory, loadSimplefinSummary]);

  const renderPane = (): ReactNode => {
    switch (activeSection) {
      case 'bank-sync':
        return (
          <BankSyncSection
            onConnectionChange={handleConnectionChange}
            cardProps={{ title: 'Connect your bank', subtitle: 'Securely sync transactions automatically (via SimpleFIN).', icon: Landmark }}
          />
        );
      case 'transactions':
        return (
          <div className="space-y-5">
            <TransactionMatchingSection
              refreshKey={transactionRefreshKey}
              simplefinConn={simplefinConn}
              cardProps={{ title: 'Review & match transactions', subtitle: 'Confirm which transactions paid which bills.', icon: ArrowRightLeft }}
            />
            <BillRulesManager />
          </div>
        );
      case 'import':
        return (
          <div className="space-y-5">
            <Suspense fallback={<PaneSkeleton />}>
              <ImportSpreadsheetSection
                onHistoryRefresh={loadHistory}
                cardProps={{ title: 'Import a spreadsheet', subtitle: 'Bring in bill & payment history from Excel.', icon: FileSpreadsheet, collapsible: true, defaultOpen: true, storageKey: 'billtracker:data.card.spreadsheet', summary: 'Import bill/payment history from an XLSX workbook.' }}
              />
            </Suspense>
            <ImportTransactionCsvSection
              onHistoryRefresh={handleTransactionImportComplete}
              cardProps={{ title: 'Import transactions (CSV)', subtitle: 'Upload a bank or card CSV export.', icon: FileText, collapsible: true, defaultOpen: false, storageKey: 'billtracker:data.card.transactionCsv', summary: 'Upload bank or credit-card CSV transaction files.' }}
            />
            <ImportOfxSection
              onHistoryRefresh={handleTransactionImportComplete}
              cardProps={{ title: 'Import transactions (OFX/QFX)', subtitle: 'Upload a bank OFX or QFX export — no column mapping needed.', icon: FileText, collapsible: true, defaultOpen: false, storageKey: 'billtracker:data.card.ofx', summary: 'Upload an OFX/QFX transaction file.' }}
            />
            <SeedDemoDataSection
              onSeeded={loadHistory}
              cardProps={{ title: 'Sample data', subtitle: 'Load or clear demo data to explore features.', icon: FlaskConical, collapsible: true, defaultOpen: false, storageKey: 'billtracker:data.card.demo', summary: 'Seed or clear demo data for testing.' }}
            />
          </div>
        );
      case 'export':
        return (
          <div className="space-y-5">
            <DownloadMyDataSection
              cardProps={{ title: 'Download your data', subtitle: 'Export a full SQLite backup or an Excel file.', icon: Download }}
            />
            <Suspense fallback={<PaneSkeleton />}>
              <ImportMyDataSection
                onHistoryRefresh={loadHistory}
                cardProps={{ title: 'Restore from a backup', subtitle: 'Load a previous SQLite export of your data.', icon: RotateCcw, collapsible: true, defaultOpen: false, storageKey: 'billtracker:data.card.sqliteImport', summary: 'Restore data from a user SQLite export.' }}
              />
            </Suspense>
            <ImportHistorySection
              history={history}
              loading={historyLoading}
              onRefresh={loadHistory}
              cardProps={{ title: 'Recent activity', subtitle: 'A log of your past imports.', icon: History, collapsible: true, defaultOpen: false, storageKey: 'billtracker:data.card.history', summary: historyLoading ? 'Loading…' : `${history?.length || 0} import record${(history?.length || 0) === 1 ? '' : 's'}.` }}
            />
            <EraseDataSection
              onErased={handleErased}
              cardProps={{ title: 'Erase my data', subtitle: 'Permanently wipe your financial data and start fresh.', icon: ShieldAlert, collapsible: true, defaultOpen: false, storageKey: 'billtracker:data.card.erase', summary: 'Danger zone — permanently delete your data.' }}
            />
          </div>
        );
      default:
        return null;
    }
  };

  const motionProps = reduceMotion
    ? {}
    : { initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -6 }, transition: { duration: 0.15 } };

  // Health dot for Bank sync + "N to review" badge for Transactions.
  const bankDot = (syncError || !syncEnabled || !hasConnections) ? 'gray' : simplefinConn?.last_error ? 'amber' : 'green';
  const navSections: DataNavSection[] = SECTIONS.map(s =>
    s.id === 'bank-sync' ? { ...s, dot: bankDot }
    : s.id === 'transactions' ? { ...s, badge: unmatchedCount || undefined }
    : s,
  );

  return (
    <div className="mx-auto w-full max-w-6xl space-y-5">
      <div className="flex flex-col gap-2 sm:flex-row sm:items-end sm:justify-between">
        <div>
          <h1 className="text-2xl font-bold tracking-tight">Data</h1>
          <p className="mt-0.5 text-sm text-muted-foreground">
            Manage how your bills, payments &amp; transactions get in and out.
          </p>
        </div>
        <TooltipProvider delayDuration={300}>
          <Tooltip>
            <TooltipTrigger asChild>
              <div className="rounded-full border border-border/70 bg-card/80 px-3 py-1.5 text-xs font-medium text-muted-foreground cursor-default">
                User data only
              </div>
            </TooltipTrigger>
            <TooltipContent>This page only manages your own records — other users' data is not accessible here</TooltipContent>
          </Tooltip>
        </TooltipProvider>
      </div>

      <ConnectionHero
        loading={syncLoading}
        error={syncError}
        enabled={syncEnabled}
        hasConnections={hasConnections}
        conn={simplefinConn}
        txnTotal={txnTotal}
        onRetry={loadSimplefinSummary}
        onGoTo={goTo}
        onSynced={handleSynced}
      />

      <div className="grid gap-5 lg:grid-cols-[220px_1fr]">
        <DataNav sections={navSections} active={activeSection} onSelect={goTo} />
        <div ref={paneRef} tabIndex={-1} className="min-w-0 outline-none">
          <AnimatePresence mode="wait">
            <motion.div key={activeSection} {...motionProps}>
              {renderPane()}
            </motion.div>
          </AnimatePresence>
        </div>
      </div>
    </div>
  );
}
