import { useCallback, useEffect, useMemo, useState, type DragEvent, type DragEventHandler } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { useSummary } from '@/hooks/useQueries';
import { toast } from 'sonner';
import {
  ArrowDown,
  ArrowUp,
  CalendarDays,
  CheckCircle2,
  ChevronLeft,
  ChevronRight,
  Edit3,
  GripVertical,
  Loader2,
  Minus,
  Printer,
  RotateCcw,
  Save,
} from 'lucide-react';
import { api } from '@/api';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { cn, errMessage } from '@/lib/utils';
import { formatUSD, asDollars } from '@/lib/money';
import { moveInArray, reorderPayload } from '@/lib/reorder';

function fmt(v: number | null | undefined): string {
  return formatUSD(asDollars(Number(v) || 0));
}

interface SummaryExpense {
  bill_id: number;
  name: string;
  category_name?: string | null;
  due_day?: number | null;
  autopay_enabled?: number;
  is_subscription?: number;
  has_merchant_rule?: unknown;
  has_linked_transactions?: unknown;
  is_paid?: boolean;
  is_skipped?: boolean;
  actual_amount?: number | null;
  display_amount?: number;
}

interface SummaryChartRow {
  type: string;
  amount: number;
}

interface StartingAmounts {
  first_amount?: number;
  fifteenth_amount?: number;
  other_amount?: number;
  combined_amount?: number;
  paid_total?: number;
  combined_remaining?: number;
}

interface SummarySummary {
  expense_total?: number;
  result?: number;
  paid_expense_count?: number;
  expense_count?: number;
  [key: string]: unknown;
}

interface SummaryResponse {
  year: number;
  month: number;
  summary?: SummarySummary;
  expenses?: SummaryExpense[];
  starting_amounts?: StartingAmounts;
  income?: { amount?: number; label?: string };
  chart?: SummaryChartRow[];
  generated_at?: string;
  previous_month?: { combined_remaining?: number };
  [key: string]: unknown;
}

interface ExpenseMoveControls {
  enabled: boolean;
  moving: boolean;
  canMoveUp: boolean;
  canMoveDown: boolean;
  onMoveUp: () => void;
  onMoveDown: () => void;
}

interface ExpenseDragProps {
  draggable: boolean;
  isDragging?: boolean;
  isDropTarget?: boolean;
  onDragStart?: DragEventHandler<HTMLDivElement>;
  onDragEnter?: DragEventHandler<HTMLDivElement>;
  onDragOver?: DragEventHandler<HTMLDivElement>;
  onDragEnd?: DragEventHandler<HTMLDivElement>;
  onDrop?: DragEventHandler<HTMLDivElement>;
}

const MONTHS = [
  'January', 'February', 'March', 'April', 'May', 'June',
  'July', 'August', 'September', 'October', 'November', 'December',
];

function selectedFromToday() {
  const now = new Date();
  return { year: now.getFullYear(), month: now.getMonth() + 1 };
}

function shiftMonth(year: number, month: number, delta: number) {
  const next = new Date(year, month - 1 + delta, 1);
  return { year: next.getFullYear(), month: next.getMonth() + 1 };
}

function monthLabel(year: number, month: number): string {
  return `${MONTHS[month - 1]} ${year}`;
}

function moneyClass(value: number): string {
  return value >= 0 ? 'text-emerald-600 dark:text-emerald-400' : 'text-destructive';
}

function StatusMark({ expense }: { expense: SummaryExpense }) {
  if (expense.is_skipped) {
    return (
      <span className="inline-flex min-w-16 items-center justify-center rounded-full bg-muted px-2 py-1 text-xs font-medium text-muted-foreground">
        Skipped
      </span>
    );
  }

  if (expense.is_paid) {
    return (
      <span className="inline-flex min-w-16 items-center justify-center gap-1 rounded-full bg-emerald-500/10 px-2 py-1 text-xs font-semibold text-emerald-700 dark:text-emerald-300">
        <CheckCircle2 className="h-3.5 w-3.5" />
        Paid
      </span>
    );
  }

  return (
    <span className="inline-flex min-w-16 items-center justify-center gap-1 rounded-full bg-muted px-2 py-1 text-xs font-medium text-muted-foreground">
      <Minus className="h-3.5 w-3.5" />
      Open
    </span>
  );
}

function SummaryChart({ rows = [], onStartingClick }: { rows?: SummaryChartRow[]; onStartingClick?: () => void }) {
  const max = Math.max(1, ...rows.map(row => Math.abs(Number(row.amount) || 0)));
  const chartRows = rows.map((row, index) => ({
    ...row,
    label: row.type === 'Remaining'
      ? Number(row.amount) >= 0 ? 'Remaining' : 'Shortfall'
      : row.type,
    color: index === 0
      ? 'hsl(var(--chart-1))'
      : index === 1
        ? 'hsl(var(--chart-3))'
        : Number(row.amount) >= 0
          ? 'hsl(var(--chart-2))'
          : 'hsl(var(--destructive))',
    width: Math.max(2, (Math.abs(Number(row.amount) || 0) / max) * 100),
  }));

  return (
    <div className="space-y-3">
      {chartRows.map(row => {
        const isStarting = row.type === 'Starting';
        const clickable  = isStarting && !!onStartingClick;
        return (
          <div key={row.type} className="grid gap-2 sm:grid-cols-[5.75rem_minmax(0,1fr)_7rem] sm:items-center">
            {clickable ? (
              <button
                type="button"
                onClick={onStartingClick}
                className="text-sm font-medium text-foreground text-left underline underline-offset-2 decoration-dashed decoration-muted-foreground/50 hover:text-primary transition-colors"
                title="Click to see income breakdown"
              >
                {row.label}
              </button>
            ) : (
              <div className="text-sm font-medium text-foreground">{row.label}</div>
            )}
            <div className="h-7 rounded-full bg-muted/70 p-1">
              <div
                className={cn('h-full rounded-full transition-[width]', clickable && 'cursor-pointer')}
                style={{ width: `${Math.min(row.width, 100)}%`, backgroundColor: row.color }}
                title={`${row.label}: ${fmt(row.amount)}`}
                onClick={clickable ? onStartingClick : undefined}
              />
            </div>
            <div className={cn('text-sm font-semibold sm:text-right', row.type === 'Remaining' ? moneyClass(row.amount) : 'text-foreground')}>
              {fmt(row.amount)}
            </div>
          </div>
        );
      })}
    </div>
  );
}

function ExpenseRow({ expense, moveControls, dragProps }: {
  expense: SummaryExpense;
  moveControls?: ExpenseMoveControls;
  dragProps?: ExpenseDragProps;
}) {
  return (
    <div
      draggable={dragProps?.draggable}
      onDragStart={dragProps?.onDragStart}
      onDragEnter={dragProps?.onDragEnter}
      onDragOver={dragProps?.onDragOver}
      onDragEnd={dragProps?.onDragEnd}
      onDrop={dragProps?.onDrop}
      className={cn(
        'summary-expense-row group grid gap-2 border-b border-border/60 px-1 py-3 last:border-0 sm:grid-cols-[auto_minmax(0,1fr)_7.5rem_5.5rem] sm:items-center',
        dragProps?.isDragging && 'opacity-45',
        dragProps?.isDropTarget && 'ring-2 ring-inset ring-primary/35',
      )}
    >
      <div className="summary-reorder-controls flex shrink-0 items-center gap-0.5 self-start sm:self-center">
        <GripVertical
          className={cn(
            'h-4 w-4 text-muted-foreground/55',
            moveControls?.enabled && 'cursor-grab group-active:cursor-grabbing',
            !moveControls?.enabled && 'opacity-30',
          )}
          aria-hidden="true"
        />
        <div className="flex flex-col">
          <button
            type="button"
            onClick={moveControls?.onMoveUp}
            disabled={!moveControls?.enabled || !moveControls?.canMoveUp || moveControls?.moving}
            className="rounded text-muted-foreground transition-colors hover:bg-accent hover:text-foreground disabled:pointer-events-none disabled:opacity-25"
            title="Move expense up"
            aria-label={`Move ${expense.name} up`}
          >
            <ArrowUp className="h-3 w-3" />
          </button>
          <button
            type="button"
            onClick={moveControls?.onMoveDown}
            disabled={!moveControls?.enabled || !moveControls?.canMoveDown || moveControls?.moving}
            className="rounded text-muted-foreground transition-colors hover:bg-accent hover:text-foreground disabled:pointer-events-none disabled:opacity-25"
            title="Move expense down"
            aria-label={`Move ${expense.name} down`}
          >
            <ArrowDown className="h-3 w-3" />
          </button>
        </div>
      </div>
      <div className="min-w-0">
        <div className="flex flex-wrap items-center gap-1.5">
          <span className="truncate text-sm font-semibold text-foreground">{expense.name}</span>
          <TooltipProvider delayDuration={300}>
            {expense.autopay_enabled ? (
              <Tooltip>
                <TooltipTrigger asChild>
                  <span className="inline-flex shrink-0 rounded border border-sky-500/25 bg-sky-500/10 px-1.5 py-0.5 text-[10px] font-bold leading-none text-sky-600 dark:text-sky-300 cursor-default">
                    AP
                  </span>
                </TooltipTrigger>
                <TooltipContent>Autopay enabled</TooltipContent>
              </Tooltip>
            ) : null}
            {expense.is_subscription ? (
              <Tooltip>
                <TooltipTrigger asChild>
                  <span className="inline-flex shrink-0 rounded border border-indigo-500/25 bg-indigo-500/10 px-1.5 py-0.5 text-[10px] font-bold leading-none text-indigo-600 dark:text-indigo-300 cursor-default">
                    S
                  </span>
                </TooltipTrigger>
                <TooltipContent>Subscription</TooltipContent>
              </Tooltip>
            ) : null}
            {(expense.has_merchant_rule || expense.has_linked_transactions) ? (
              <Tooltip>
                <TooltipTrigger asChild>
                  <span className="inline-flex shrink-0 rounded border border-emerald-500/25 bg-emerald-500/10 px-1.5 py-0.5 text-[10px] font-bold leading-none text-emerald-600 dark:text-emerald-400 cursor-default">
                    L
                  </span>
                </TooltipTrigger>
                <TooltipContent>Linked to bank transactions</TooltipContent>
              </Tooltip>
            ) : null}
          </TooltipProvider>
        </div>
        <div className="mt-1 flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
          {expense.category_name && <span>{expense.category_name}</span>}
          <span>Due day {expense.due_day}</span>
          {expense.actual_amount !== null && <span>Monthly amount</span>}
        </div>
      </div>
      <div className="text-sm font-semibold text-foreground sm:text-right">{fmt(expense.display_amount)}</div>
      <div className="sm:justify-self-end" aria-label={expense.is_paid ? 'Paid' : expense.is_skipped ? 'Skipped' : 'Open'}>
        <StatusMark expense={expense} />
      </div>
    </div>
  );
}

export default function SummaryPage() {
  const [selected, setSelected] = useState(selectedFromToday);
  const queryClient = useQueryClient();
  const { data: dataRaw, isPending: loading, error: queryError } = useSummary(selected.year, selected.month);
  const data = (dataRaw ?? null) as SummaryResponse | null;
  const setData = useCallback(
    (updater: (prev: SummaryResponse | null | undefined) => SummaryResponse | null | undefined) =>
      queryClient.setQueryData<SummaryResponse | null>(['summary', selected.year, selected.month], updater),
    [queryClient, selected.year, selected.month],
  );
  const [saving, setSaving] = useState(false);
  const error = queryError ? (queryError.message || 'Summary could not be loaded.') : '';
  const [startingFirst, setStartingFirst] = useState('0');
  const [startingFifteenth, setStartingFifteenth] = useState('0');
  const [startingOther, setStartingOther] = useState('0');
  const [editingStarting, setEditingStarting] = useState(false);
  const [incomeAmount, setIncomeAmount] = useState('0');
  const [incomeLabel,  setIncomeLabel]  = useState('Salary');
  const [editingIncome, setEditingIncome] = useState(false);
  const [draggingId, setDraggingId] = useState<number | null>(null);
  const [dropTargetId, setDropTargetId] = useState<number | null>(null);
  const [movingBillId, setMovingBillId] = useState<number | null>(null);

  const loadSummary = useCallback(
    () => queryClient.invalidateQueries({ queryKey: ['summary', selected.year, selected.month] }),
    [queryClient, selected.month, selected.year],
  );

  // Seed the editable form fields (starting amounts, income) from the loaded
  // summary and reset transient edit/drag state whenever the data changes.
  useEffect(() => {
    if (!data) return;
    setStartingFirst(String(data.starting_amounts?.first_amount ?? 0));
    setStartingFifteenth(String(data.starting_amounts?.fifteenth_amount ?? 0));
    setStartingOther(String(data.starting_amounts?.other_amount ?? 0));
    setEditingStarting(false);
    setIncomeAmount(String(data.income?.amount ?? 0));
    setIncomeLabel(data.income?.label || 'Salary');
    setEditingIncome(false);
    setDraggingId(null);
    setDropTargetId(null);
    setMovingBillId(null);
  }, [data]);

  const summary = data?.summary || {};
  const expenses = data?.expenses || [];
  const starting = data?.starting_amounts || {};
  const reorderEnabled = !loading && !error && expenses.length > 1;

  const generatedLabel = useMemo(() => {
    if (!data?.generated_at) return '';
    return new Date(data.generated_at).toLocaleString();
  }, [data?.generated_at]);

  async function saveStartingAmounts() {
    const first = Number(startingFirst);
    const fifteenth = Number(startingFifteenth);
    const other = Number(startingOther);
    if (![first, fifteenth, other].every(value => Number.isFinite(value) && value >= 0)) {
      toast.error('Enter non-negative starting amounts.');
      return;
    }

    setSaving(true);
    try {
      await api.updateMonthlyStartingAmounts({
        year: selected.year,
        month: selected.month,
        first_amount: first,
        fifteenth_amount: fifteenth,
        other_amount: other,
      });
      toast.success('Starting amounts saved.');
      await loadSummary();
    } catch (err) {
      toast.error(errMessage(err, 'Starting amounts could not be saved.'));
    } finally {
      setSaving(false);
    }
  }

  async function saveIncome() {
    const amount = Number(incomeAmount);
    if (!Number.isFinite(amount) || amount < 0) {
      toast.error('Enter a valid income amount.');
      return;
    }
    const label = incomeLabel.trim() || 'Salary';
    setSaving(true);
    try {
      await api.saveSummaryIncome({ year: selected.year, month: selected.month, amount, label });
      toast.success('Income saved.');
      setEditingIncome(false);
      await loadSummary();
    } catch (err) {
      toast.error(errMessage(err, 'Income could not be saved.'));
    } finally {
      setSaving(false);
    }
  }

  function moveMonth(delta: number) {
    setSelected(current => shiftMonth(current.year, current.month, delta));
  }

  function resetToday() {
    setSelected(selectedFromToday());
  }

  async function persistExpenseOrder(nextExpenses: SummaryExpense[], movedId: number | null) {
    setData(prev => prev ? { ...prev, expenses: nextExpenses } : prev);
    setMovingBillId(movedId);
    try {
      await api.reorderBills(reorderPayload(nextExpenses.map(expense => ({ id: expense.bill_id }))));
      toast.success('Summary order saved');
      await loadSummary();
    } catch (err) {
      toast.error(errMessage(err, 'Failed to save summary order.'));
      await loadSummary();
    } finally {
      setMovingBillId(null);
    }
  }

  function reorderExpenses(fromIndex: number, toIndex: number) {
    if (!reorderEnabled || fromIndex === toIndex) return;
    const nextExpenses = moveInArray(expenses, fromIndex, toIndex);
    persistExpenseOrder(nextExpenses, expenses[fromIndex]?.bill_id || null);
  }

  function moveControlsFor(expense: SummaryExpense, index: number): ExpenseMoveControls {
    return {
      enabled: reorderEnabled,
      moving: movingBillId === expense.bill_id,
      canMoveUp: index > 0,
      canMoveDown: index < expenses.length - 1,
      onMoveUp: () => reorderExpenses(index, index - 1),
      onMoveDown: () => reorderExpenses(index, index + 1),
    };
  }

  function dragPropsFor(expense: SummaryExpense, index: number): ExpenseDragProps {
    if (!reorderEnabled) return { draggable: false };
    return {
      draggable: true,
      isDragging: draggingId === expense.bill_id,
      isDropTarget: dropTargetId === expense.bill_id && draggingId !== expense.bill_id,
      onDragStart: (event: DragEvent<HTMLDivElement>) => {
        setDraggingId(expense.bill_id);
        event.dataTransfer.effectAllowed = 'move';
        event.dataTransfer.setData('text/plain', String(expense.bill_id));
      },
      onDragEnter: () => {
        if (draggingId && draggingId !== expense.bill_id) setDropTargetId(expense.bill_id);
      },
      onDragOver: (event: DragEvent<HTMLDivElement>) => {
        event.preventDefault();
        event.dataTransfer.dropEffect = 'move';
        if (draggingId && draggingId !== expense.bill_id) setDropTargetId(expense.bill_id);
      },
      onDrop: (event: DragEvent<HTMLDivElement>) => {
        event.preventDefault();
        const sourceId = Number(event.dataTransfer.getData('text/plain') || draggingId);
        const fromIndex = expenses.findIndex(item => item.bill_id === sourceId);
        if (fromIndex >= 0) reorderExpenses(fromIndex, index);
        setDraggingId(null);
        setDropTargetId(null);
      },
      onDragEnd: () => {
        setDraggingId(null);
        setDropTargetId(null);
      },
    };
  }

  return (
    <div className="summary-page mx-auto max-w-3xl space-y-5">
      <div className="summary-print-meta hidden">
        <h1>BillTracker Summary</h1>
        <p>{monthLabel(selected.year, selected.month)}</p>
        {generatedLabel && <p>Generated {generatedLabel}</p>}
      </div>

      <div className="summary-screen-header flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between">
        <div>
          <h1 className="text-3xl font-bold tracking-tight text-foreground">Summary</h1>
          <p className="mt-1 text-sm text-muted-foreground">Plan starting balance, expenses, and monthly result.</p>
        </div>
        <div className="summary-actions flex gap-2">
          <Button variant="outline" onClick={resetToday} className="sm:w-auto">
            <RotateCcw className="h-4 w-4" />
            Today
          </Button>
          <Button onClick={() => window.print()} className="sm:w-auto">
            <Printer className="h-4 w-4" />
            Print / PDF
          </Button>
        </div>
      </div>

      <div className="summary-controls mx-auto flex w-full max-w-md items-center justify-between gap-2 rounded-full border border-border/70 bg-card p-1.5 shadow-sm">
        <Button variant="ghost" size="icon" onClick={() => moveMonth(-1)} aria-label="Previous month">
          <ChevronLeft className="h-4 w-4" />
        </Button>
        <div className="flex min-w-0 flex-1 items-center justify-center gap-2 px-2 text-center">
          <CalendarDays className="hidden h-4 w-4 text-muted-foreground sm:block" />
          <div className="truncate text-base font-semibold text-foreground">{monthLabel(selected.year, selected.month)}</div>
        </div>
        <Button variant="ghost" size="icon" onClick={() => moveMonth(1)} aria-label="Next month">
          <ChevronRight className="h-4 w-4" />
        </Button>
      </div>

      {loading && (
        <Card>
          <CardContent className="flex min-h-72 items-center justify-center p-8 text-sm text-muted-foreground">
            <Loader2 className="mr-2 h-4 w-4 animate-spin" />
            Loading summary...
          </CardContent>
        </Card>
      )}

      {!loading && error && (
        <Card className="border-destructive/40">
          <CardContent className="space-y-3 p-6">
            <p className="text-sm font-medium text-destructive">{error}</p>
            <Button variant="outline" onClick={loadSummary}>Retry</Button>
          </CardContent>
        </Card>
      )}

      {!loading && !error && data && (
        <>
          <Card className="summary-card">
            <CardHeader className="pb-3">
              <CardTitle className="text-xl">Monthly Plan</CardTitle>
              <CardDescription>{monthLabel(data.year, data.month)}</CardDescription>
            </CardHeader>

            <CardContent className="space-y-5">
              <section className="space-y-3">
                <div className="flex items-center justify-between gap-3">
                  <h2 className="text-xs font-semibold uppercase tracking-normal text-muted-foreground">Starting Balance</h2>
                  <Button
                    type="button"
                    variant="ghost"
                    size="sm"
                    className="summary-edit-actions h-7 px-2"
                    onClick={() => setEditingStarting(value => !value)}
                  >
                    <Edit3 className="h-3.5 w-3.5" />
                    {editingStarting ? 'Close' : 'Edit'}
                  </Button>
                </div>

                <div className="grid gap-3 rounded-2xl bg-muted/45 p-4 sm:grid-cols-3">
                  <div>
                    <TooltipProvider delayDuration={300}>
                      <Tooltip>
                        <TooltipTrigger asChild>
                          <div className="text-xs font-medium text-muted-foreground cursor-default w-fit">1st</div>
                        </TooltipTrigger>
                        <TooltipContent>Cash on hand for bills due on the 1st–14th</TooltipContent>
                      </Tooltip>
                    </TooltipProvider>
                    <div className="tracker-number mt-1 text-base font-bold text-foreground">{fmt(starting.first_amount)}</div>
                  </div>
                  <div>
                    <TooltipProvider delayDuration={300}>
                      <Tooltip>
                        <TooltipTrigger asChild>
                          <div className="text-xs font-medium text-muted-foreground cursor-default w-fit">15th</div>
                        </TooltipTrigger>
                        <TooltipContent>Cash on hand for bills due on the 15th–31st</TooltipContent>
                      </Tooltip>
                    </TooltipProvider>
                    <div className="tracker-number mt-1 text-base font-bold text-foreground">{fmt(starting.fifteenth_amount)}</div>
                  </div>
                  <div>
                    <TooltipProvider delayDuration={300}>
                      <Tooltip>
                        <TooltipTrigger asChild>
                          <div className="text-xs font-medium text-muted-foreground cursor-default w-fit">Other</div>
                        </TooltipTrigger>
                        <TooltipContent>Additional funds not tied to a specific pay period</TooltipContent>
                      </Tooltip>
                    </TooltipProvider>
                    <div className="tracker-number mt-1 text-base font-bold text-foreground">{fmt(starting.other_amount)}</div>
                  </div>
                  <div className="border-t border-border/60 pt-3 sm:col-span-3">
                    <div className="grid gap-3 sm:grid-cols-3">
                      <div>
                        <div className="text-xs font-medium text-muted-foreground">Total starting</div>
                        <div className="tracker-number mt-1 text-lg font-bold text-foreground">{fmt(starting.combined_amount)}</div>
                      </div>
                      <div>
                        <div className="text-xs font-medium text-muted-foreground">Paid</div>
                        <div className="tracker-number mt-1 text-lg font-bold text-emerald-600 dark:text-emerald-300">{fmt(starting.paid_total)}</div>
                      </div>
                      <div>
                        <div className="text-xs font-medium text-muted-foreground">Total remaining</div>
                        <div className={cn('tracker-number mt-1 text-lg font-bold', moneyClass(starting.combined_remaining || 0))}>
                          {fmt(starting.combined_remaining)}
                        </div>
                      </div>
                    </div>
                  </div>
                </div>

                {data.previous_month && (
                  <div className="rounded-xl border border-border/60 bg-background/70 px-3 py-2 text-xs text-muted-foreground">
                    Previous month remaining: {fmt(data.previous_month.combined_remaining)}
                  </div>
                )}

                {editingStarting && (
                  <div className="summary-income-form grid gap-3 rounded-2xl border border-border/60 bg-background/80 p-3 md:grid-cols-[1fr_1fr_1fr_auto] md:items-end">
                    <label className="space-y-1">
                      <span className="text-xs font-medium text-muted-foreground">1st</span>
                      <Input type="number" min="0" step="0.01" value={startingFirst} onChange={event => setStartingFirst(event.target.value)} />
                    </label>
                    <label className="space-y-1">
                      <span className="text-xs font-medium text-muted-foreground">15th</span>
                      <Input type="number" min="0" step="0.01" value={startingFifteenth} onChange={event => setStartingFifteenth(event.target.value)} />
                    </label>
                    <label className="space-y-1">
                      <span className="text-xs font-medium text-muted-foreground">Other</span>
                      <Input type="number" min="0" step="0.01" value={startingOther} onChange={event => setStartingOther(event.target.value)} />
                    </label>
                    <Button onClick={saveStartingAmounts} disabled={saving} className="summary-edit-actions w-full md:w-auto">
                      {saving ? <Loader2 className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
                      Save
                    </Button>
                  </div>
                )}
              </section>

              <section className="space-y-3">
                <div className="flex items-center justify-between gap-3">
                  <h2 className="text-xs font-semibold uppercase tracking-normal text-muted-foreground">Monthly Income</h2>
                  <Button
                    type="button"
                    variant="ghost"
                    size="sm"
                    className="summary-edit-actions h-7 px-2"
                    onClick={() => setEditingIncome(v => !v)}
                  >
                    <Edit3 className="h-3.5 w-3.5" />
                    {editingIncome ? 'Close' : 'Edit'}
                  </Button>
                </div>

                <div className="flex items-center justify-between rounded-2xl bg-muted/45 px-4 py-3">
                  <div>
                    <div className="text-xs font-medium text-muted-foreground">{data?.income?.label || 'Salary'}</div>
                    <div className="tracker-number mt-1 text-2xl font-bold text-emerald-600 dark:text-emerald-400">
                      {fmt(data?.income?.amount ?? 0)}
                    </div>
                  </div>
                  {Number(data?.income?.amount) > 0 && Number(summary?.expense_total) > 0 && (
                    <div className="text-right">
                      <div className="text-xs text-muted-foreground">After expenses</div>
                      <div className={cn('tracker-number mt-1 text-lg font-bold', moneyClass(Number(data?.income?.amount) - Number(summary?.expense_total)))}>
                        {fmt(Number(data?.income?.amount) - Number(summary?.expense_total))}
                      </div>
                    </div>
                  )}
                </div>

                {editingIncome && (
                  <div className="grid gap-3 rounded-2xl border border-border/60 bg-background/80 p-3 md:grid-cols-[1fr_2fr_auto] md:items-end">
                    <label className="space-y-1">
                      <span className="text-xs font-medium text-muted-foreground">Label</span>
                      <Input value={incomeLabel} onChange={e => setIncomeLabel(e.target.value)} placeholder="Salary" maxLength={80} />
                    </label>
                    <label className="space-y-1">
                      <span className="text-xs font-medium text-muted-foreground">Amount</span>
                      <Input
                        type="number"
                        min="0"
                        step="0.01"
                        value={incomeAmount}
                        onChange={e => setIncomeAmount(e.target.value)}
                        onKeyDown={e => { if (e.key === 'Enter') saveIncome(); }}
                      />
                    </label>
                    <Button onClick={saveIncome} disabled={saving} className="summary-edit-actions w-full md:w-auto">
                      {saving ? <Loader2 className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
                      Save
                    </Button>
                  </div>
                )}
              </section>

              <section className="space-y-3">
                <div className="flex items-end justify-between gap-3">
                  <div>
                    <h2 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Expenses</h2>
                    <p className="mt-1 text-xs text-muted-foreground">Skipped bills are shown but not counted.</p>
                  </div>
                  <div className="hidden text-xs font-semibold uppercase tracking-wide text-muted-foreground sm:block">
                    Paid
                  </div>
                </div>

                {expenses.length === 0 ? (
                  <div className="flex flex-col items-center gap-2 rounded-xl bg-muted/20 px-6 py-10 text-center">
                    <p className="text-sm font-medium text-muted-foreground">No bills for this month</p>
                    <a href="/bills" className="text-xs text-primary underline underline-offset-4 hover:opacity-80 transition-opacity">Add a bill →</a>
                  </div>
                ) : (
                  <div className="rounded-2xl border border-border/60 bg-background/70 px-3">
                    {expenses.map((expense, index) => (
                      <ExpenseRow
                        key={expense.bill_id}
                        expense={expense}
                        moveControls={moveControlsFor(expense, index)}
                        dragProps={dragPropsFor(expense, index)}
                      />
                    ))}
                  </div>
                )}
              </section>

              <section className="space-y-3 rounded-2xl border border-border/60 bg-muted/40 p-4">
                <div className="flex items-center justify-between gap-4">
                  <div className="text-sm font-medium text-muted-foreground">Fully Paid Expenses</div>
                  <div className="text-base font-bold text-foreground">{summary.paid_expense_count || 0} / {summary.expense_count || 0}</div>
                </div>
                <div className="flex items-center justify-between gap-4">
                  <div className="text-sm font-medium text-muted-foreground">Expenses</div>
                  <div className="text-base font-semibold text-foreground">{fmt(summary.expense_total)}</div>
                </div>
                <div className="flex items-center justify-between gap-4 border-t border-border/60 pt-3">
                  <TooltipProvider delayDuration={300}>
                    <Tooltip>
                      <TooltipTrigger asChild>
                        <div className="text-base font-semibold text-foreground cursor-default">Result</div>
                      </TooltipTrigger>
                      <TooltipContent>Starting balance minus total planned expenses</TooltipContent>
                    </Tooltip>
                  </TooltipProvider>
                  <div className={cn('text-2xl font-bold', moneyClass(summary.result || 0))}>{fmt(summary.result)}</div>
                </div>
              </section>

              <Button onClick={() => window.print()} className="summary-actions w-full">
                <Printer className="h-4 w-4" />
                Print / PDF
              </Button>
            </CardContent>
          </Card>

          <Card className="summary-chart-card">
            <CardHeader className="pb-3">
              <CardTitle className="text-xl">Total amount per type</CardTitle>
              <CardDescription>
                Starting balance, planned expenses, and {Number(summary.result || 0) >= 0 ? 'remaining' : 'shortfall'} for {monthLabel(data.year, data.month)}.
              </CardDescription>
            </CardHeader>
            <CardContent>
              <SummaryChart rows={data.chart || []} />
            </CardContent>
          </Card>

          <div className="summary-print-footer hidden text-xs text-muted-foreground">
            Generated {generatedLabel || 'now'}
          </div>
        </>
      )}

    </div>
  );
}
