import { useEffect, useState, useMemo } from 'react';
import { Link } from 'react-router-dom';
import {
  ArrowRight,
  TrendingUp,
  TrendingDown,
  RefreshCw,
  CreditCard,
  Pencil,
  Check,
  X,
  BellRing,
  Landmark,
} from 'lucide-react';

import api, { type Account, type Transaction } from '../api';
import { useSettings } from '@/hooks/useSettings';
import { formatAmount, formatDate, formatLocalDatetime } from '@/lib/format';
import DashboardSection from '@/components/DashboardSection';
import SectionConfigDialog from '@/components/SectionConfigDialog';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { cn } from '@/lib/utils';

// --- Section definitions ---

interface SectionDef {
  filterFn: (a: Account) => boolean;
  totalCurrency: string; // empty string = no total
}

const SECTION_DEFS: Record<string, SectionDef> = {
  crc_accounts: { filterFn: (a) => a.account_type === 'BANK' && a.currency === 'CRC', totalCurrency: 'CRC' },
  usd_accounts: { filterFn: (a) => a.account_type === 'BANK' && a.currency === 'USD', totalCurrency: 'USD' },
  pension:      { filterFn: (a) => a.account_type === 'PENSION', totalCurrency: 'CRC' },
  savings:      { filterFn: (a) => a.account_type === 'SAVINGS', totalCurrency: 'CRC' },
  liabilities:  { filterFn: (a) => a.account_type === 'LIABILITY', totalCurrency: '' },
  crypto:       { filterFn: (a) => a.account_type === 'CRYPTO', totalCurrency: '' },
};

const BANK_ORDER = ['BAC', 'BCR', 'DAVIVIENDA'];

// --- AccountRow ---

interface AccountRowProps {
  account: Account;
  editingId: number | null;
  editValue: string;
  setEditValue: (v: string) => void;
  startEditing: (a: Account) => void;
  saveBalance: (id: number) => void;
  cancelEditing: () => void;
}

function AccountRow({
  account,
  editingId,
  editValue,
  setEditValue,
  startEditing,
  saveBalance,
  cancelEditing,
}: AccountRowProps) {
  const isLiability = account.account_type === 'LIABILITY';
  const isCrypto = account.account_type === 'CRYPTO';
  const label = isCrypto ? account.label : (account.bank === 'DAVIVIENDA' ? 'DAV' : account.bank);
  const isEditing = editingId === account.id;

  return (
    <div className="flex items-center justify-between px-3 py-2.5 hover:bg-muted/30 transition-colors group">
      <span className="text-sm font-medium text-muted-foreground">{label}</span>

      {isEditing ? (
        <div className="flex items-center gap-2">
          <Input
            type="number"
            step="0.01"
            value={editValue}
            onChange={(e) => setEditValue(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === 'Enter') saveBalance(account.id);
              if (e.key === 'Escape') cancelEditing();
            }}
            autoFocus
            className="text-sm font-bold font-mono tracking-tight h-auto py-1 w-40"
          />
          <Button variant="ghost" size="icon-xs" onClick={() => saveBalance(account.id)} title="Save" aria-label="Save balance">
            <Check className="w-3.5 h-3.5" />
          </Button>
          <Button variant="ghost" size="icon-xs" onClick={cancelEditing} title="Cancel" aria-label="Cancel editing">
            <X className="w-3.5 h-3.5" />
          </Button>
        </div>
      ) : (
        <div className="flex items-center gap-1.5">
          <span data-sensitive className={cn('text-lg font-bold font-mono tracking-tight', isLiability && 'text-destructive')}>
            {formatAmount(account.balance, account.currency)}
          </span>
          <button
            onClick={() => startEditing(account)}
            className="opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground hover:text-foreground cursor-pointer"
            title="Edit balance"
            aria-label="Edit balance"
          >
            <Pencil className="w-3.5 h-3.5" />
          </button>
          {isLiability && account.next_payment != null && (
            <span data-sensitive className="text-xs font-mono text-destructive/60 ml-2">
              Next: {formatAmount(account.next_payment, account.currency)}
            </span>
          )}
        </div>
      )}
    </div>
  );
}

// --- Dashboard ---

export default function Dashboard() {
  const [accounts, setAccounts] = useState<Account[]>([]);
  const [recent, setRecent] = useState<Transaction[]>([]);
  const [loading, setLoading] = useState(true);
  const [editingId, setEditingId] = useState<number | null>(null);
  const [editValue, setEditValue] = useState('');
  const [exchangeRate, setExchangeRate] = useState<{ buy_rate: number; sell_rate: number } | null>(null);
  const [configSection, setConfigSection] = useState<string | null>(null);
  const [testingPush, setTestingPush] = useState(false);

  const { settings, patchSection } = useSettings();

  const fetchData = async () => {
    setLoading(true);
    try {
      const [accRes, txRes] = await Promise.all([
        api.get('/accounts/'),
        api.get('/transactions/recent?limit=5'),
      ]);
      setAccounts(accRes.data);
      setRecent(txRes.data);
    } catch (e) {
      console.error(e);
    } finally {
      setLoading(false);
    }
    api.get('/exchange-rate/').then((r) => setExchangeRate(r.data)).catch(() => {});
  };

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

  const startEditing = (account: Account) => {
    setEditingId(account.id);
    setEditValue(String(account.balance));
  };
  const cancelEditing = () => { setEditingId(null); setEditValue(''); };
  const saveBalance = async (accountId: number) => {
    const parsed = parseFloat(editValue);
    if (isNaN(parsed)) return cancelEditing();
    try {
      await api.patch(`/accounts/${accountId}`, { balance: parsed });
      setEditingId(null);
      setEditValue('');
      fetchData();
    } catch (e) { console.error(e); }
  };

  const rowProps = { editingId, editValue, setEditValue, startEditing, saveBalance, cancelEditing };

  // Sort sections by order, filter by visible
  const sortedSections = useMemo(() => {
    const sections = settings.dashboard.sections;
    return Object.entries(sections)
      .filter(([, s]) => s.visible)
      .sort(([, a], [, b]) => a.order - b.order);
  }, [settings]);

  // Net worth calculation
  const netWorthBreakdown = useMemo(() => {
    if (accounts.length === 0) return null;
    let assets = 0;
    let liabilities = 0;
    for (const a of accounts) {
      const isLiability = a.account_type === 'LIABILITY';
      let crcValue = 0;
      if (a.currency === 'USD') {
        crcValue = Math.abs(a.balance) * (exchangeRate?.sell_rate ?? 0);
      } else if (a.currency === 'CRC') {
        crcValue = Math.abs(a.balance);
      }
      if (isLiability) {
        liabilities += crcValue;
      } else {
        assets += crcValue;
      }
    }
    return { assets, liabilities, net: assets - liabilities };
  }, [accounts, exchangeRate]);

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold font-heading">Dashboard</h1>
          <p className="text-sm text-muted-foreground mt-1">Financial overview</p>
        </div>
        <Button variant="ghost" size="icon" onClick={fetchData} title="Refresh" aria-label="Refresh">
          <RefreshCw className={cn('w-4 h-4', loading && 'animate-spin')} />
        </Button>
      </div>

      {/* Net Worth */}
      {netWorthBreakdown != null && (
        <Card>
          <CardContent className="px-4 py-3">
            <div className="flex items-center justify-between text-sm font-mono text-muted-foreground">
              <span>Net <span data-sensitive className="text-foreground font-bold">{netWorthBreakdown.net < 0 ? '-' : ''}{formatAmount(netWorthBreakdown.net, 'CRC')}</span></span>
              <div className="flex gap-4">
                <span>Assets <span data-sensitive className="text-foreground">{formatAmount(netWorthBreakdown.assets, 'CRC')}</span></span>
                <span>Liabilities <span data-sensitive className="text-foreground">{formatAmount(netWorthBreakdown.liabilities, 'CRC')}</span></span>
              </div>
            </div>
          </CardContent>
        </Card>
      )}

      {/* Account sections */}
      {sortedSections.map(([sectionId, sectionSettings]) => {
        const def = SECTION_DEFS[sectionId];
        if (!def) return null;
        let accts = accounts.filter(def.filterFn);
        if (accts.length === 0) return null;

        // Sort bank accounts by bank order
        if (sectionId === 'crc_accounts' || sectionId === 'usd_accounts') {
          accts = accts.sort((a, b) => BANK_ORDER.indexOf(a.bank) - BANK_ORDER.indexOf(b.bank));
        }

        const total = accts.reduce((s, a) => s + a.balance, 0);

        return (
          <DashboardSection
            key={sectionId}
            sectionId={sectionId}
            settings={sectionSettings}
            total={def.totalCurrency ? total : undefined}
            totalCurrency={def.totalCurrency || undefined}
            onToggleExpanded={(expanded) => patchSection(sectionId, { expanded })}
            onOpenConfig={() => setConfigSection(sectionId)}
          >
            {accts.map((a) => (
              <AccountRow key={a.id} account={a} {...rowProps} />
            ))}
          </DashboardSection>
        );
      })}

      {/* Exchange rate */}
      {exchangeRate && (
        <Card>
          <CardContent className="p-4">
            <span className="text-xs font-medium text-muted-foreground uppercase tracking-wider">USD/CRC Exchange Rate</span>
            <div className="flex items-baseline gap-3 mt-1">
              <span data-sensitive className="text-lg font-bold font-mono">Buy: ₡{exchangeRate.buy_rate.toFixed(2)}</span>
              <span data-sensitive className="text-lg font-bold font-mono text-muted-foreground">Sell: ₡{exchangeRate.sell_rate.toFixed(2)}</span>
            </div>
          </CardContent>
        </Card>
      )}

      {/* Recent transactions */}
      <Card>
        <CardHeader className="border-b flex-row items-center justify-between">
          <div className="flex items-center gap-2">
            <CreditCard className="w-4 h-4 text-muted-foreground" />
            <CardTitle className="text-sm">Recent Charges</CardTitle>
          </div>
          <Link
            to="/transactions"
            className="flex items-center gap-1 text-xs font-medium text-primary hover:text-primary/80 transition-colors"
          >
            View all
            <ArrowRight className="w-3 h-3" />
          </Link>
        </CardHeader>
        <CardContent className="p-0">
          {recent.length === 0 && !loading ? (
            <div className="px-5 py-12 text-center text-muted-foreground text-sm">No transactions yet. Add your first one!</div>
          ) : (
            <div className="divide-y divide-border">
              {recent.map((tx) => (
                <div key={tx.id} className="flex items-center justify-between px-5 py-3.5 hover:bg-muted/50 transition-colors">
                  <div className="flex items-center gap-3 min-w-0">
                    <div className={cn(
                      'w-8 h-8 rounded-lg flex items-center justify-center shrink-0',
                      tx.transaction_type === 'COMPRA' ? 'bg-destructive/10 text-destructive' : 'bg-primary/10 text-primary'
                    )}>
                      {tx.transaction_type === 'DEPOSITO' ? <Landmark className="w-4 h-4" /> : tx.transaction_type === 'DEVOLUCION' ? <TrendingUp className="w-4 h-4" /> : <TrendingDown className="w-4 h-4" />}
                    </div>
                    <div className="min-w-0">
                      <p className="text-sm font-medium truncate">{tx.merchant}</p>
                      <p className="text-xs text-muted-foreground">
                        {formatDate(tx.date)}
                        {tx.category && <span className="ml-2 text-muted-foreground/60">{tx.category.name}</span>}
                      </p>
                    </div>
                  </div>
                  <span data-sensitive className={cn(
                    'font-mono text-sm font-medium shrink-0 ml-4',
                    tx.transaction_type !== 'COMPRA' && 'text-primary'
                  )}>
                    {tx.transaction_type === 'COMPRA' ? '-' : '+'}{formatAmount(tx.amount, tx.currency)}
                  </span>
                </div>
              ))}
            </div>
          )}
        </CardContent>
      </Card>

      {/* Test push notification */}
      <Card className="border-dashed border-yellow-500/50">
        <CardContent className="p-4 flex items-center justify-between">
          <div>
            <p className="text-sm font-medium">Test Push Notification</p>
            <p className="text-xs text-muted-foreground">Creates a mock transaction to trigger a push notification</p>
          </div>
          <Button
            variant="outline"
            size="sm"
            disabled={testingPush}
            onClick={async () => {
              setTestingPush(true);
              try {
                const merchants = ['Walmart', 'AutoMercado', 'Uber Eats', 'Amazon', 'PriceSmart'];
                const amounts = [4500, 12350, 8900, 25000, 67800];
                const i = Math.floor(Math.random() * merchants.length);
                await api.post('/transactions/', {
                  merchant: merchants[i],
                  amount: amounts[i],
                  currency: 'CRC',
                  date: formatLocalDatetime(new Date()),
                  bank: 'BAC',
                  source: 'CREDIT_CARD',
                  transaction_type: 'COMPRA',
                  reference: `test-push-${Date.now()}`,
                  notes: '[TEST] Push notification test — safe to delete',
                });
                fetchData();
              } catch (e) {
                console.error('Test push failed:', e);
              } finally {
                setTestingPush(false);
              }
            }}
          >
            <BellRing className="w-4 h-4 mr-2" />
            {testingPush ? 'Sending...' : 'Send test'}
          </Button>
        </CardContent>
      </Card>

      {/* Section config dialog */}
      {configSection && settings.dashboard.sections[configSection] && (
        <SectionConfigDialog
          sectionId={configSection}
          settings={settings.dashboard.sections[configSection]}
          open={!!configSection}
          onOpenChange={(open) => { if (!open) setConfigSection(null); }}
          onSave={(id, partial) => patchSection(id, partial)}
        />
      )}
    </div>
  );
}
