import { useState, useEffect, useCallback } from 'react';
import { toast } from 'sonner';
import { formatUSD, asDollars, type Dollars } from '@/lib/money';
import { TrendingUp, EyeOff, Eye, Loader2 } from 'lucide-react';
import { api } from '@/api';
import { errMessage } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import {
  Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription,
} from '@/components/ui/dialog';

function fmt(n: Parameters<typeof formatUSD>[0]): string {
  return formatUSD(n);
}

interface IncomeTx {
  id: number | string;
  payee?: string | null;
  date?: string | null;
  amount: Dollars;
  ignored?: boolean;
}

interface IncomeBt {
  enabled?: boolean;
  org_name?: string | null;
  account_name?: string | null;
  balance?: Dollars;
  pending_payments?: Dollars;
  pending_days?: number;
  effective_balance?: Dollars;
}

interface IncomeBreakdownModalProps {
  open: boolean;
  onClose: () => void;
  year: number;
  month: number;
  bankTracking?: IncomeBt | null;
}

export default function IncomeBreakdownModal({ open, onClose, year, month, bankTracking }: IncomeBreakdownModalProps) {
  const [transactions, setTransactions] = useState<IncomeTx[]>([]);
  const [loading,      setLoading]      = useState(false);
  const [loadError,    setLoadError]    = useState('');
  const [showIgnored,  setShowIgnored]  = useState(false);
  const [actionId,     setActionId]     = useState<number | string | null>(null);

  const load = useCallback(async () => {
    if (!open) return;
    setLoading(true);
    setLoadError('');
    try {
      const d = await api.spendingIncome({ year, month, include_ignored: showIgnored ? 'true' : undefined, limit: 100 }) as { transactions?: IncomeTx[] };
      setTransactions(d.transactions || []);
    } catch (err) {
      const msg = errMessage(err, 'Failed to load income transactions');
      setLoadError(msg);
      toast.error(msg);
    } finally {
      setLoading(false);
    }
  }, [open, year, month, showIgnored]);

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

  const handleIgnore = async (tx: IncomeTx) => {
    setActionId(tx.id);
    try {
      await api.ignoreTransaction(tx.id);
      toast.success(`"${tx.payee}" marked as excluded`);
    } catch (err) {
      toast.error(errMessage(err, 'Failed to exclude transaction'));
      setActionId(null);
      return; // don't reload if the action itself failed
    }
    setActionId(null);
    await load(); // reload outside the action try so load errors are surfaced separately
  };

  const handleUnignore = async (tx: IncomeTx) => {
    setActionId(tx.id);
    try {
      await api.unignoreTransaction(tx.id);
      toast.success(`"${tx.payee}" restored as income`);
    } catch (err) {
      toast.error(errMessage(err, 'Failed to restore transaction'));
      setActionId(null);
      return;
    }
    setActionId(null);
    await load();
  };

  const active   = transactions.filter(t => !t.ignored);
  const ignored  = transactions.filter(t => t.ignored);
  const total    = asDollars(active.reduce((s, t) => s + t.amount, 0));

  const bt = bankTracking || {};

  return (
    <Dialog open={open} onOpenChange={v => { if (!v) onClose(); }}>
      <DialogContent className="sm:max-w-lg border-border/60 bg-card/95 backdrop-blur-xl">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2 text-base">
            <TrendingUp className="h-4 w-4 text-emerald-500" />
            Starting Balance Breakdown
          </DialogTitle>
          <DialogDescription className="sr-only">
            How your starting balance was calculated from your bank account
          </DialogDescription>
        </DialogHeader>

        {/* Balance calculation */}
        {bt.enabled && (
          <div className="rounded-xl border border-border/60 bg-muted/20 px-4 py-3 space-y-2 text-sm">
            <div className="flex items-center justify-between">
              <span className="text-muted-foreground">{bt.org_name || bt.account_name || 'Bank'} balance</span>
              <span className="font-mono font-semibold">{fmt(bt.balance)}</span>
            </div>
            {(bt.pending_payments ?? 0) > 0 && (
              <div className="flex items-center justify-between text-muted-foreground">
                <span>Pending payments ({bt.pending_days}d window)</span>
                <span className="font-mono text-destructive">−{fmt(bt.pending_payments)}</span>
              </div>
            )}
            <div className="flex items-center justify-between border-t border-border/50 pt-2 font-medium">
              <span>Effective starting balance</span>
              <span className="font-mono text-emerald-500">{fmt(bt.effective_balance)}</span>
            </div>
          </div>
        )}

        {/* Income transactions */}
        <div className="space-y-2">
          <div className="flex items-center justify-between">
            <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
              Income this month
            </p>
            <div className="flex items-center gap-2">
              {ignored.length > 0 || showIgnored ? (
                <button
                  type="button"
                  onClick={() => setShowIgnored(v => !v)}
                  className="text-xs text-muted-foreground underline-offset-4 hover:underline hover:text-foreground transition-colors flex items-center gap-1"
                >
                  {showIgnored ? <EyeOff className="h-3 w-3" /> : <Eye className="h-3 w-3" />}
                  {showIgnored ? 'Hide excluded' : `Show excluded (${ignored.length})`}
                </button>
              ) : null}
              {active.length > 0 && (
                <span className="text-xs font-semibold text-emerald-500 font-mono">{fmt(total)}</span>
              )}
            </div>
          </div>

          {loading ? (
            <div className="flex items-center justify-center py-6 gap-2 text-muted-foreground text-sm">
              <Loader2 className="h-4 w-4 animate-spin" /> Loading…
            </div>
          ) : loadError ? (
            <div className="flex flex-col items-center gap-2 py-6 text-center">
              <p className="text-sm text-destructive">{loadError}</p>
              <Button variant="outline" size="sm" onClick={load}>Retry</Button>
            </div>
          ) : transactions.length === 0 ? (
            <p className="text-sm text-muted-foreground text-center py-4">
              No income transactions found for this month.
            </p>
          ) : (
            <div className="divide-y divide-border/30 rounded-xl border border-border/60 bg-muted/10 overflow-hidden max-h-72 overflow-y-auto">
              {active.map(tx => (
                <div key={tx.id} className="flex items-center gap-3 px-3 py-2.5 hover:bg-muted/20 transition-colors">
                  <div className="min-w-0 flex-1">
                    <p className="text-sm font-medium truncate">{tx.payee}</p>
                    <p className="text-xs text-muted-foreground">{tx.date}</p>
                  </div>
                  <span className="text-sm font-mono font-semibold text-emerald-500 shrink-0">+{fmt(tx.amount)}</span>
                  <button
                    type="button"
                    disabled={actionId === tx.id}
                    onClick={() => handleIgnore(tx)}
                    title="Exclude — mark as transfer or non-income"
                    className="shrink-0 text-xs text-muted-foreground hover:text-destructive transition-colors flex items-center gap-1 disabled:opacity-40"
                  >
                    <EyeOff className="h-3.5 w-3.5" />
                  </button>
                </div>
              ))}

              {showIgnored && ignored.map(tx => (
                <div key={tx.id} className="flex items-center gap-3 px-3 py-2.5 bg-muted/5 opacity-60">
                  <div className="min-w-0 flex-1">
                    <p className="text-sm line-through truncate text-muted-foreground">{tx.payee}</p>
                    <p className="text-xs text-muted-foreground">{tx.date}</p>
                  </div>
                  <span className="text-sm font-mono text-muted-foreground shrink-0">+{fmt(tx.amount)}</span>
                  <button
                    type="button"
                    disabled={actionId === tx.id}
                    onClick={() => handleUnignore(tx)}
                    title="Restore as income"
                    className="shrink-0 text-xs text-muted-foreground hover:text-emerald-500 transition-colors flex items-center gap-1 disabled:opacity-40"
                  >
                    <Eye className="h-3.5 w-3.5" />
                  </button>
                </div>
              ))}
            </div>
          )}
        </div>

        <p className="text-[10px] text-muted-foreground/60 text-center">
          Showing positive unmatched transactions from your bank. Exclude transfers or non-income deposits.
        </p>
      </DialogContent>
    </Dialog>
  );
}
