import React, { useState, useEffect, useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { toast } from 'sonner';
import { AlertCircle, Building2, Link2Off, Loader2, Moon, RefreshCw, Sun, Users } from 'lucide-react';
import { api } from '@/api';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import {
  AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent,
  AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import {
  Select, SelectTrigger, SelectValue, SelectContent, SelectItem,
} from '@/components/ui/select';
import { useTheme } from '@/contexts/ThemeContext';
import { useAuth } from '@/hooks/useAuth';

// ─── Card wrapper ─────────────────────────────────────────────────────────────

function SectionCard({ title, children }) {
  return (
    <div className="table-surface mb-4">
      <div className="px-6 py-4 border-b border-border/50">
        <h2 className="text-xs font-bold uppercase tracking-widest text-muted-foreground">{title}</h2>
      </div>
      <div className="divide-y divide-border/50">
        {children}
      </div>
    </div>
  );
}

// ─── Setting Row ──────────────────────────────────────────────────────────────

function SettingRow({ label, description, children }) {
  return (
    <div className="px-4 py-4 flex flex-col gap-3 sm:px-6 sm:flex-row sm:items-center sm:justify-between">
      <div className="flex-1 min-w-0 sm:mr-8">
        <p className="text-sm font-medium">{label}</p>
        {description && (
          <p className="text-xs text-muted-foreground mt-0.5">{description}</p>
        )}
      </div>
      <div className="shrink-0">
        {children}
      </div>
    </div>
  );
}

// ─── Theme Card ───────────────────────────────────────────────────────────────

function ThemeCard({ value, label, icon: Icon, currentTheme, onSelect }) {
  const selected = currentTheme === value;
  return (
    <button
      type="button"
      onClick={() => onSelect(value)}
      className={cn(
        'flex flex-col items-center gap-1.5 rounded-lg border px-3 py-2.5 text-xs font-medium transition-all',
        'hover:border-muted-foreground/50',
        selected
          ? 'border-primary bg-primary/5 text-primary'
          : 'border-border bg-card text-muted-foreground',
      )}
    >
      <Icon className="h-4 w-4" />
      <span>{label}</span>
    </button>
  );
}

// ─── Appearance Section ───────────────────────────────────────────────────────

function AppearanceSection() {
  const { theme, setTheme } = useTheme();

  return (
    <SectionCard title="Appearance">
      <SettingRow label="Theme" description="Choose your preferred color scheme.">
        <div className="flex gap-2">
          <ThemeCard value="light" label="Light" icon={Sun} currentTheme={theme} onSelect={setTheme} />
          <ThemeCard value="dark"  label="Dark"  icon={Moon} currentTheme={theme} onSelect={setTheme} />
        </div>
      </SettingRow>
    </SectionCard>
  );
}

function LoginModeRecoverySection() {
  const navigate = useNavigate();
  const { singleUserMode, refresh } = useAuth();
  const [restoring, setRestoring] = useState(false);

  if (!singleUserMode) return null;

  const handleRestore = async () => {
    setRestoring(true);
    try {
      await api.restoreMultiUserMode();
      toast.success('Multi-user login restored.');
      refresh();
      navigate('/login', { replace: true });
    } catch (err) {
      toast.error(err.message || 'Failed to restore multi-user mode.');
    } finally {
      setRestoring(false);
    }
  };

  return (
    <SectionCard title="Login Mode">
      <SettingRow
        label="Single-user mode is active"
        description="Restore the normal login screen so each user signs in with their own account."
      >
        <Button size="sm" variant="outline" onClick={handleRestore} disabled={restoring}>
          <Users className="h-3.5 w-3.5 mr-1.5" />
          {restoring ? 'Restoring…' : 'Restore Multi-User Mode'}
        </Button>
      </SettingRow>
    </SectionCard>
  );
}

// ─── Settings Skeleton ────────────────────────────────────────────────────────

function SettingsSkeleton() {
  return (
    <div>
      {/* Page header */}
      <div className="mb-8">
        <h1 className="h-8 w-48 rounded-md bg-muted/50"></h1>
        <p className="h-4 w-64 mt-2 rounded-md bg-muted/50"></p>
      </div>

      {/* Appearance */}
      <div className="table-surface mb-4">
        <div className="px-6 py-4 border-b border-border/50">
          <h2 className="h-3 w-24 rounded bg-muted/50"></h2>
        </div>
        <div className="divide-y divide-border/50">
          <div className="px-6 py-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
            <div className="flex-1 min-w-0 sm:mr-8">
              <p className="h-4 w-32 rounded-md bg-muted/50"></p>
              <p className="h-3 w-48 mt-2 rounded-md bg-muted/50"></p>
            </div>
            <div className="shrink-0 flex gap-2">
              <div className="h-12 w-20 rounded-lg bg-muted/50"></div>
              <div className="h-12 w-20 rounded-lg bg-muted/50"></div>
            </div>
          </div>
        </div>
      </div>

      {/* Login mode */}
      <div className="table-surface mb-4">
        <div className="px-6 py-4 border-b border-border/50">
          <h2 className="h-3 w-24 rounded bg-muted/50"></h2>
        </div>
        <div className="divide-y divide-border/50">
          <div className="px-6 py-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
            <div className="flex-1 min-w-0 sm:mr-8">
              <p className="h-4 w-48 rounded-md bg-muted/50"></p>
              <p className="h-3 w-64 mt-2 rounded-md bg-muted/50"></p>
            </div>
            <div className="shrink-0 h-9 w-48 rounded-md bg-muted/50"></div>
          </div>
        </div>
      </div>

      {/* General */}
      <div className="table-surface mb-4">
        <div className="px-6 py-4 border-b border-border/50">
          <h2 className="h-3 w-24 rounded bg-muted/50"></h2>
        </div>
        <div className="divide-y divide-border/50">
          <div className="px-6 py-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
            <div className="flex-1 min-w-0 sm:mr-8">
              <p className="h-4 w-32 rounded-md bg-muted/50"></p>
              <p className="h-3 w-48 mt-2 rounded-md bg-muted/50"></p>
            </div>
            <div className="shrink-0 h-9 w-32 rounded-md bg-muted/50"></div>
          </div>
          <div className="px-6 py-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
            <div className="flex-1 min-w-0 sm:mr-8">
              <p className="h-4 w-32 rounded-md bg-muted/50"></p>
              <p className="h-3 w-48 mt-2 rounded-md bg-muted/50"></p>
            </div>
            <div className="shrink-0 h-9 w-32 rounded-md bg-muted/50"></div>
          </div>
        </div>
      </div>

      {/* Billing */}
      <div className="table-surface mb-4">
        <div className="px-6 py-4 border-b border-border/50">
          <h2 className="h-3 w-24 rounded bg-muted/50"></h2>
        </div>
        <div className="divide-y divide-border/50">
          <div className="px-6 py-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
            <div className="flex-1 min-w-0 sm:mr-8">
              <p className="h-4 w-32 rounded-md bg-muted/50"></p>
              <p className="h-3 w-48 mt-2 rounded-md bg-muted/50"></p>
            </div>
            <div className="shrink-0 h-9 w-32 rounded-md bg-muted/50"></div>
          </div>
        </div>
      </div>
    </div>
  );
}

// ─── Bank Sync Section ────────────────────────────────────────────────────────

function BankSyncSection() {
  const [enabled, setEnabled]         = useState(null);   // null = loading
  const [connections, setConnections] = useState([]);
  const [loadError, setLoadError]     = useState('');
  const [setupToken, setSetupToken]   = useState('');
  const [connecting, setConnecting]   = useState(false);
  const [syncing, setSyncing]         = useState(null);   // id being synced
  const [disconnectTarget, setDisconnectTarget] = useState(null);
  const [disconnecting, setDisconnecting]       = useState(false);

  const load = useCallback(async () => {
    setLoadError('');
    try {
      const [status, sources] = await Promise.all([
        api.simplefinStatus(),
        api.dataSources({ type: 'provider_sync' }),
      ]);
      setEnabled(status.enabled);
      setConnections(Array.isArray(sources) ? sources.filter(s => s.provider === 'simplefin') : []);
    } catch (err) {
      setEnabled(false);
      setLoadError(err.message || 'Failed to load bank sync status');
    }
  }, []);

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

  const handleConnect = async () => {
    const token = setupToken.trim();
    if (!token) { toast.error('Paste your SimpleFIN setup token first.'); return; }
    setConnecting(true);
    try {
      const result = await api.connectSimplefin(token);
      toast.success(`Connected — ${result.accountsUpserted} account(s), ${result.transactionsNew} new transaction(s).`);
      setSetupToken('');
      await load();
    } catch (err) {
      toast.error(err.message || 'Failed to connect SimpleFIN');
    } finally {
      setConnecting(false);
    }
  };

  const handleSync = async (id) => {
    setSyncing(id);
    try {
      const result = await api.syncDataSource(id);
      toast.success(`Synced — ${result.transactionsNew} new transaction(s).`);
      await load();
    } catch (err) {
      toast.error(err.message || 'Sync failed');
      await load();
    } finally {
      setSyncing(null);
    }
  };

  const handleDisconnect = async () => {
    if (!disconnectTarget) return;
    setDisconnecting(true);
    try {
      await api.deleteDataSource(disconnectTarget.id);
      toast.success('SimpleFIN disconnected.');
      setDisconnectTarget(null);
      await load();
    } catch (err) {
      toast.error(err.message || 'Failed to disconnect');
    } finally {
      setDisconnecting(false);
    }
  };

  function fmtDate(iso) {
    if (!iso) return '—';
    return new Date(iso).toLocaleString(undefined, { month: 'short', day: 'numeric', year: 'numeric', hour: '2-digit', minute: '2-digit' });
  }

  if (enabled === null) {
    return (
      <SectionCard title="Bank Sync">
        <div className="px-6 py-6 flex items-center gap-2 text-sm text-muted-foreground">
          <Loader2 className="h-4 w-4 animate-spin" />
          Loading…
        </div>
      </SectionCard>
    );
  }

  return (
    <>
      <SectionCard title="Bank Sync">
        {!enabled ? (
          <div className="px-6 py-5 text-sm text-muted-foreground">
            Bank sync is not enabled on this server.
            Set <code className="rounded bg-muted px-1 py-0.5 text-xs font-mono">BANK_SYNC_ENABLED=true</code> and
            a <code className="rounded bg-muted px-1 py-0.5 text-xs font-mono">TOKEN_ENCRYPTION_KEY</code> in your
            environment to enable SimpleFIN.
          </div>
        ) : (
          <>
            {loadError && (
              <div className="px-6 py-3 text-sm text-destructive">{loadError}</div>
            )}

            {/* Connected accounts */}
            {connections.length > 0 && connections.map(conn => (
              <div key={conn.id} className="px-6 py-4 space-y-3">
                <div className="flex items-start justify-between gap-3">
                  <div className="flex items-center gap-3 min-w-0">
                    <Building2 className="h-5 w-5 shrink-0 text-muted-foreground" />
                    <div className="min-w-0">
                      <p className="text-sm font-medium truncate">{conn.name}</p>
                      <p className="text-xs text-muted-foreground mt-0.5">
                        {conn.account_count} account{conn.account_count !== 1 ? 's' : ''} ·{' '}
                        {conn.transaction_count} transaction{conn.transaction_count !== 1 ? 's' : ''}
                      </p>
                    </div>
                  </div>
                  <div className="flex items-center gap-2 shrink-0">
                    <Button
                      size="sm" variant="outline"
                      onClick={() => handleSync(conn.id)}
                      disabled={syncing === conn.id}
                      className="h-8 text-xs gap-1.5"
                    >
                      {syncing === conn.id
                        ? <><Loader2 className="h-3.5 w-3.5 animate-spin" />Syncing…</>
                        : <><RefreshCw className="h-3.5 w-3.5" />Sync Now</>}
                    </Button>
                    <Button
                      size="sm" variant="ghost"
                      onClick={() => setDisconnectTarget(conn)}
                      className="h-8 text-xs gap-1.5 text-muted-foreground hover:text-destructive"
                    >
                      <Link2Off className="h-3.5 w-3.5" />
                      Disconnect
                    </Button>
                  </div>
                </div>

                <div className="grid grid-cols-2 gap-2 sm:grid-cols-3 text-xs">
                  <div className="rounded-lg border border-border/60 bg-muted/20 px-3 py-2">
                    <p className="text-muted-foreground">Last sync</p>
                    <p className="font-medium mt-0.5">{fmtDate(conn.last_sync_at)}</p>
                  </div>
                  <div className={cn(
                    'rounded-lg border px-3 py-2',
                    conn.last_error ? 'border-destructive/30 bg-destructive/5' : 'border-border/60 bg-muted/20',
                  )}>
                    <p className="text-muted-foreground">Status</p>
                    <p className={cn('font-medium mt-0.5', conn.last_error ? 'text-destructive' : '')}>
                      {conn.last_error ? conn.last_error : (conn.status === 'active' ? 'Active' : conn.status)}
                    </p>
                  </div>
                </div>
              </div>
            ))}

            {/* Connect form */}
            {connections.length === 0 && (
              <div className="px-6 py-5 space-y-4">
                <div className="rounded-lg border border-border/60 bg-muted/20 p-4 text-sm text-muted-foreground">
                  <p className="font-medium text-foreground mb-1">Connect a SimpleFIN Bridge account</p>
                  <p>Paste your SimpleFIN setup token below. BillTracker only stores an encrypted access URL — no bank credentials are saved.</p>
                </div>
                <div className="flex gap-2">
                  <Input
                    value={setupToken}
                    onChange={e => setSetupToken(e.target.value)}
                    placeholder="Paste SimpleFIN setup token…"
                    className="flex-1 font-mono text-xs"
                  />
                  <Button
                    onClick={handleConnect}
                    disabled={connecting || !setupToken.trim()}
                    className="shrink-0"
                  >
                    {connecting ? <><Loader2 className="h-4 w-4 animate-spin mr-1.5" />Connecting…</> : 'Connect'}
                  </Button>
                </div>
              </div>
            )}

            {/* Add another connection — only show if already connected */}
            {connections.length > 0 && (
              <div className="px-6 py-4 border-t border-border/50 space-y-2">
                <p className="text-xs font-medium text-muted-foreground">Add another connection</p>
                <div className="flex gap-2">
                  <Input
                    value={setupToken}
                    onChange={e => setSetupToken(e.target.value)}
                    placeholder="Paste SimpleFIN setup token…"
                    className="flex-1 font-mono text-xs"
                  />
                  <Button
                    size="sm"
                    onClick={handleConnect}
                    disabled={connecting || !setupToken.trim()}
                    className="shrink-0"
                  >
                    {connecting ? <><Loader2 className="h-3.5 w-3.5 animate-spin mr-1" />Connecting…</> : 'Connect'}
                  </Button>
                </div>
              </div>
            )}
          </>
        )}
      </SectionCard>

      <AlertDialog open={!!disconnectTarget} onOpenChange={open => { if (!open) setDisconnectTarget(null); }}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Disconnect SimpleFIN?</AlertDialogTitle>
            <AlertDialogDescription>
              This removes the connection and deletes synced accounts. Previously synced transactions
              are kept but will no longer be associated with a data source.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={disconnecting}>Cancel</AlertDialogCancel>
            <AlertDialogAction onClick={handleDisconnect} disabled={disconnecting}
              className="bg-destructive text-destructive-foreground hover:bg-destructive/90">
              {disconnecting ? 'Disconnecting…' : 'Disconnect'}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </>
  );
}

// ─── SettingsPage ─────────────────────────────────────────────────────────────

export default function SettingsPage() {
  const DEFAULTS = {
    currency:              'USD',
    date_format:           'MM/DD/YYYY',
    grace_period_days:     3,
  };

  const [settings, setSettings] = useState(DEFAULTS);
  const [loading,   setLoading]   = useState(true);
  const [loadError, setLoadError] = useState(null);
  const [saving,    setSaving]    = useState(false);

  const loadSettings = useCallback(() => {
    setLoading(true);
    setLoadError(null);
    api.settings()
      .then((d) => setSettings({ ...DEFAULTS, ...d }))
      .catch((err) => setLoadError(err.message || 'Failed to load settings'))
      .finally(() => setLoading(false));
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

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

  const set = (k, v) => setSettings((p) => ({ ...p, [k]: v }));

  const handleSave = async () => {
    setSaving(true);
    try {
      await api.saveSettings({
        currency: settings.currency,
        date_format: settings.date_format,
        grace_period_days: settings.grace_period_days,
      });
      toast.success('Settings saved.');
    } catch (err) {
      toast.error(err.message || 'Failed to save settings.');
    } finally {
      setSaving(false);
    }
  };

  if (loading) {
    return (
      <div className="flex items-center justify-center py-12">
        <SettingsSkeleton />
      </div>
    );
  }

  if (loadError) {
    return (
      <div className="flex flex-col items-center justify-center py-24 text-center rounded-xl border border-destructive/20 bg-destructive/5">
        <AlertCircle className="h-10 w-10 text-destructive mb-3" />
        <p className="text-sm font-medium text-foreground">Failed to load settings</p>
        <p className="mt-1 text-xs text-muted-foreground">{loadError}</p>
        <Button size="sm" variant="outline" onClick={loadSettings}
          className="mt-4 gap-1.5 text-xs border-destructive/30 hover:bg-destructive/10 hover:text-destructive hover:border-destructive/50">
          <RefreshCw className="h-3 w-3" />
          Try again
        </Button>
      </div>
    );
  }

  return (
    <div>

      {/* Page header — flat on background */}
      <div className="mb-8">
        <h1 className="text-2xl font-bold tracking-tight">Settings</h1>
        <p className="text-sm text-muted-foreground mt-0.5">Manage your display and billing preferences</p>
      </div>

      {/* Appearance */}
      <AppearanceSection />

      {/* Login mode recovery */}
      <LoginModeRecoverySection />

      {/* General */}
      <SectionCard title="General">
        <SettingRow label="Currency" description="Default currency for bill amounts.">
          <Select value={settings.currency} onValueChange={(v) => set('currency', v)}>
            <SelectTrigger className="w-48">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="USD">USD — US Dollar</SelectItem>
              <SelectItem value="EUR">EUR — Euro</SelectItem>
              <SelectItem value="GBP">GBP — British Pound</SelectItem>
              <SelectItem value="CAD">CAD — Canadian Dollar</SelectItem>
            </SelectContent>
          </Select>
        </SettingRow>

        <SettingRow label="Date format" description="How dates are displayed throughout the app.">
          <Select value={settings.date_format} onValueChange={(v) => set('date_format', v)}>
            <SelectTrigger className="w-48">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="MM/DD/YYYY">MM/DD/YYYY</SelectItem>
              <SelectItem value="DD/MM/YYYY">DD/MM/YYYY</SelectItem>
              <SelectItem value="YYYY-MM-DD">YYYY-MM-DD</SelectItem>
            </SelectContent>
          </Select>
        </SettingRow>
      </SectionCard>

      {/* Billing Behavior */}
      <SectionCard title="Billing Behavior">
        <SettingRow
          label="Grace period"
          description="Days after the due date before a bill is marked overdue."
        >
          <div className="flex items-center gap-2">
            <Input
              type="number"
              min={0}
              max={30}
              value={settings.grace_period_days}
              onChange={(e) => set('grace_period_days', parseInt(e.target.value, 10) || 0)}
              className="w-20"
            />
            <span className="text-sm text-muted-foreground">days</span>
          </div>
        </SettingRow>
      </SectionCard>

      {/* Bank Sync */}
      <BankSyncSection />

      {/* Save button — right-aligned below all cards */}
      <div className="flex justify-end mt-6">
        <Button size="sm" onClick={handleSave} disabled={saving}>
          {saving ? 'Saving…' : 'Save Settings'}
        </Button>
      </div>

    </div>
  );
}
