import { useState, type ComponentType, type ReactNode } from 'react';
import { toast } from 'sonner';
import { Landmark, RefreshCw, Loader2, AlertTriangle, RotateCcw, Upload, Plus } from 'lucide-react';
import { api } from '@/api';
import { cn, errMessage } from '@/lib/utils';
import { Button } from '@/components/ui/button';

// Relative "2h ago" / "3d ago"; returns null for empty input.
function relativeTime(iso: string | null | undefined): string | null {
  if (!iso) return null;
  const then = new Date(iso).getTime();
  if (Number.isNaN(then)) return null;
  const secs = Math.max(0, Math.round((Date.now() - then) / 1000));
  if (secs < 60) return 'just now';
  const mins = Math.round(secs / 60);
  if (mins < 60) return `${mins}m ago`;
  const hrs = Math.round(mins / 60);
  if (hrs < 24) return `${hrs}h ago`;
  const days = Math.round(hrs / 24);
  return `${days}d ago`;
}

function HeroShell({ tone = 'default', icon: Icon, children }: {
  tone?: string;
  icon: ComponentType<{ className?: string }>;
  children: ReactNode;
}) {
  const toneRing = ({
    default: 'border-border/60',
    good: 'border-emerald-500/30',
    warn: 'border-amber-500/40',
    error: 'border-rose-500/30',
  } as Record<string, string>)[tone];
  const toneChip = ({
    default: 'bg-muted/50 text-muted-foreground',
    good: 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400',
    warn: 'bg-amber-500/10 text-amber-600 dark:text-amber-400',
    error: 'bg-rose-500/10 text-rose-600 dark:text-rose-400',
  } as Record<string, string>)[tone];
  return (
    <div className={cn('surface flex flex-col gap-3 p-5 sm:flex-row sm:items-center sm:gap-4', toneRing)}>
      <span className={cn('grid h-11 w-11 shrink-0 place-items-center rounded-xl', toneChip)}>
        <Icon className="h-5 w-5" />
      </span>
      {children}
    </div>
  );
}

interface ConnData {
  name?: string | null;
  last_sync_at?: string | null;
  last_error?: string | null;
}

interface ConnectionHeroProps {
  loading?: boolean;
  error?: unknown;          // truthy when the status/summary fetch failed
  enabled?: boolean;        // status.enabled (server feature flag)
  hasConnections?: boolean; // status.has_connections
  conn?: ConnData | null;   // the simplefin data_source (name, last_sync_at, last_error) or null
  txnTotal?: number | null; // total synced transactions (at-a-glance), or null
  onRetry?: () => void;
  onGoTo?: (sectionId: string) => void;  // (sectionId) => void
  onSynced?: () => void;                 // () => void — refresh after a successful sync
}

/**
 * The Data page's connection status hero. Five states, so a network blip is never
 * mistaken for "not connected", and a server without bank sync never gets a dead
 * Connect button:
 *   loading · disabled · error · not-connected · connected (± needs-attention)
 */
export default function ConnectionHero({
  loading,
  error,
  enabled,
  hasConnections,
  conn,
  txnTotal,
  onRetry,
  onGoTo,
  onSynced,
}: ConnectionHeroProps) {
  const [syncing, setSyncing] = useState(false);

  async function handleSyncNow() {
    setSyncing(true);
    try {
      const r = await api.syncAllSources() as { errors?: unknown[]; transactions_new?: number };
      const errs = Array.isArray(r?.errors) ? r.errors : [];
      if (errs.length) {
        toast.warning(`Synced, but ${errs.length} connection${errs.length === 1 ? '' : 's'} need attention.`);
      } else {
        const n = r?.transactions_new ?? 0;
        toast.success(`Synced — ${n} new transaction${n === 1 ? '' : 's'}.`);
      }
      onSynced?.();
    } catch (err) {
      if ((err as { status?: number })?.status === 429) toast.error('Please wait a moment before syncing again.');
      else toast.error(errMessage(err, 'Sync failed.'));
    } finally {
      setSyncing(false);
    }
  }

  // ── loading ──
  if (loading) {
    return (
      <div className="surface flex items-center gap-4 p-5">
        <span className="h-11 w-11 shrink-0 animate-pulse rounded-xl bg-muted/50" />
        <div className="flex-1 space-y-2">
          <div className="h-4 w-48 animate-pulse rounded bg-muted/50" />
          <div className="h-3 w-32 animate-pulse rounded bg-muted/40" />
        </div>
      </div>
    );
  }

  // ── disabled (server has no bank sync) ──
  if (!enabled) {
    return (
      <HeroShell icon={Landmark}>
        <div className="min-w-0 flex-1">
          <p className="text-sm font-semibold text-foreground">Automatic bank sync isn’t enabled</p>
          <p className="mt-0.5 text-sm text-muted-foreground">
            This server doesn’t have SimpleFIN configured — you can still import and export your data.
          </p>
        </div>
        <Button variant="outline" className="shrink-0 gap-2" onClick={() => onGoTo?.('import')}>
          <Upload className="h-4 w-4" /> Import data
        </Button>
      </HeroShell>
    );
  }

  // ── error (couldn't check) ──
  if (error) {
    return (
      <HeroShell tone="error" icon={AlertTriangle}>
        <div className="min-w-0 flex-1">
          <p className="text-sm font-semibold text-foreground">Couldn’t check your bank connection</p>
          <p className="mt-0.5 text-sm text-muted-foreground">Something went wrong loading your sync status.</p>
        </div>
        <Button variant="outline" className="shrink-0 gap-2" onClick={onRetry}>
          <RotateCcw className="h-4 w-4" /> Retry
        </Button>
      </HeroShell>
    );
  }

  // ── not connected ──
  if (!hasConnections || !conn) {
    return (
      <HeroShell icon={Landmark}>
        <div className="min-w-0 flex-1">
          <p className="text-sm font-semibold text-foreground">Connect your bank to get started</p>
          <p className="mt-0.5 text-sm text-muted-foreground">
            Sync transactions automatically, or import your existing history.
          </p>
        </div>
        <div className="flex shrink-0 flex-wrap gap-2">
          <Button className="gap-2" onClick={() => onGoTo?.('bank-sync')}>
            <Plus className="h-4 w-4" /> Connect your bank
          </Button>
          <Button variant="outline" className="gap-2" onClick={() => onGoTo?.('import')}>
            <Upload className="h-4 w-4" /> Import data
          </Button>
        </div>
      </HeroShell>
    );
  }

  // ── connected (± needs attention) ──
  const needsAttention = Boolean(conn.last_error);
  const synced = relativeTime(conn.last_sync_at);
  return (
    <HeroShell tone={needsAttention ? 'warn' : 'good'} icon={needsAttention ? AlertTriangle : Landmark}>
      <div className="min-w-0 flex-1">
        <p className="text-sm font-semibold text-foreground">
          {needsAttention ? 'Your bank connection needs attention' : 'Your bank is connected'}
        </p>
        <p className="mt-0.5 truncate text-sm text-muted-foreground">
          {needsAttention
            ? conn.last_error
            : (
              <>
                {conn.name || 'SimpleFIN'}
                {Number(txnTotal) > 0 ? <> · {Number(txnTotal).toLocaleString('en-US')} transactions</> : null}
                {synced ? <> · synced {synced}</> : null}
                {' · syncs automatically'}
              </>
            )}
        </p>
      </div>
      <div className="flex shrink-0 flex-wrap gap-2">
        {needsAttention && (
          <Button variant="outline" className="gap-2" onClick={() => onGoTo?.('bank-sync')}>
            <RotateCcw className="h-4 w-4" /> Reconnect
          </Button>
        )}
        <Button className="gap-2" onClick={handleSyncNow} disabled={syncing}>
          {syncing ? <Loader2 className="h-4 w-4 animate-spin" /> : <RefreshCw className="h-4 w-4" />}
          {syncing ? 'Syncing…' : 'Sync now'}
        </Button>
      </div>
    </HeroShell>
  );
}
