import { useState, useEffect, useCallback, useRef } from 'react';
import { toast } from 'sonner';
import { ChevronLeft, ChevronRight, MoreHorizontal, ReceiptText } from 'lucide-react';
import { api } from '@/api.js';
import { cn, fmt, fmtDate, todayStr } from '@/lib/utils';
import { Button, buttonVariants } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from '@/components/ui/dialog';
import {
  AlertDialog,
  AlertDialogContent,
  AlertDialogHeader,
  AlertDialogFooter,
  AlertDialogTitle,
  AlertDialogDescription,
  AlertDialogCancel,
  AlertDialogAction,
} from '@/components/ui/alert-dialog';
import {
  DropdownMenu,
  DropdownMenuTrigger,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
} from '@/components/ui/dropdown-menu';
import {
  Select,
  SelectTrigger,
  SelectValue,
  SelectContent,
  SelectItem,
} from '@/components/ui/select';
import {
  Table,
  TableHeader,
  TableBody,
  TableHead,
  TableRow,
  TableCell,
} from '@/components/ui/table';

// ─── Constants ────────────────────────────────────────────────────────────────

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

const PAYMENT_METHODS = [
  { value: 'bank_transfer', label: 'Bank Transfer' },
  { value: 'card',          label: 'Card' },
  { value: 'autopay',       label: 'Autopay' },
  { value: 'check',         label: 'Check' },
  { value: 'cash',          label: 'Cash' },
  { value: 'other',         label: 'Other' },
];

// ─── Status Config ────────────────────────────────────────────────────────────

const STATUS = {
  paid:      { label: 'Paid',      dot: 'bg-emerald-400', chip: 'bg-emerald-500/10 text-emerald-500' },
  upcoming:  { label: 'Upcoming',  dot: 'bg-slate-400',   chip: 'bg-slate-500/10   text-slate-500 dark:text-slate-400' },
  due_soon:  { label: 'Due Soon',  dot: 'bg-amber-400',   chip: 'bg-amber-500/10   text-amber-600 dark:text-amber-400' },
  late:      { label: 'Late',      dot: 'bg-orange-400',  chip: 'bg-orange-500/10  text-orange-600 dark:text-orange-400' },
  missed:    { label: 'Missed',    dot: 'bg-red-400',     chip: 'bg-red-500/10     text-red-500' },
  autodraft: { label: 'Autodraft', dot: 'bg-violet-400',  chip: 'bg-violet-500/10  text-violet-500' },
};

// ─── Status Chip ──────────────────────────────────────────────────────────────

function StatusChip({ status }) {
  const cfg = STATUS[status] ?? { label: status, dot: 'bg-slate-400', chip: 'bg-slate-500/10 text-slate-500' };
  return (
    <span className={cn('inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs font-medium', cfg.chip)}>
      <span className={cn('h-1.5 w-1.5 rounded-full', cfg.dot)} />
      {cfg.label}
    </span>
  );
}

// ─── Payment Dialog ───────────────────────────────────────────────────────────

function PaymentDialog({ open, onOpenChange, bill, payment, onSuccess }) {
  const isEdit = !!payment;

  const [form, setForm] = useState({
    amount:    '',
    paid_date: todayStr(),
    method:    '',
    notes:     '',
  });
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    if (!open) return;
    if (isEdit) {
      setForm({
        amount:    String(payment.amount ?? ''),
        paid_date: payment.paid_date ?? todayStr(),
        method:    payment.method ?? '',
        notes:     payment.notes ?? '',
      });
    } else {
      setForm({
        amount:    String(bill?.expected_amount ?? ''),
        paid_date: todayStr(),
        method:    '',
        notes:     '',
      });
    }
  }, [open, isEdit, payment, bill]);

  const set = (key) => (e) => setForm((f) => ({ ...f, [key]: e.target.value }));

  async function handleSubmit() {
    if (!form.amount || !form.paid_date) {
      toast.error('Amount and date are required');
      return;
    }
    const amount = parseFloat(form.amount);
    if (isNaN(amount) || amount <= 0) {
      toast.error('Enter a valid amount');
      return;
    }
    setSaving(true);
    try {
      const payload = {
        amount,
        paid_date: form.paid_date,
        method:    form.method || null,
        notes:     form.notes  || null,
      };
      if (isEdit) {
        await api.updatePayment(payment.id, payload);
        toast.success('Payment updated');
      } else {
        await api.quickPay({ bill_id: bill.id, ...payload });
        toast.success(`Paid ${fmt(amount)} for ${bill.name}`);
      }
      onOpenChange(false);
      onSuccess?.();
    } catch (err) {
      toast.error(err.message);
    } finally {
      setSaving(false);
    }
  }

  const title = isEdit
    ? `Edit Payment — ${bill?.name ?? ''}`
    : `Record Payment — ${bill?.name ?? ''}`;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-md">
        <DialogHeader>
          <DialogTitle>{title}</DialogTitle>
        </DialogHeader>

        <div className="flex flex-col gap-4 py-1">
          {/* Amount */}
          <div className="space-y-1.5">
            <Label htmlFor="pd-amount">Amount</Label>
            <div className="relative">
              <span className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground">
                $
              </span>
              <Input
                id="pd-amount"
                type="number"
                step="0.01"
                min="0"
                placeholder="0.00"
                className="pl-7 font-mono"
                value={form.amount}
                onChange={set('amount')}
              />
            </div>
          </div>

          {/* Date Paid */}
          <div className="space-y-1.5">
            <Label htmlFor="pd-date">Date Paid</Label>
            <Input
              id="pd-date"
              type="date"
              value={form.paid_date}
              onChange={set('paid_date')}
            />
          </div>

          {/* Method */}
          <div className="space-y-1.5">
            <Label htmlFor="pd-method">Method</Label>
            <Select value={form.method} onValueChange={(v) => setForm((f) => ({ ...f, method: v }))}>
              <SelectTrigger id="pd-method">
                <SelectValue placeholder="Select method…" />
              </SelectTrigger>
              <SelectContent>
                {PAYMENT_METHODS.map((m) => (
                  <SelectItem key={m.value} value={m.value}>{m.label}</SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          {/* Notes */}
          <div className="space-y-1.5">
            <Label htmlFor="pd-notes">Notes</Label>
            <Input
              id="pd-notes"
              placeholder="Add a note…"
              value={form.notes}
              onChange={set('notes')}
            />
          </div>
        </div>

        <DialogFooter className="gap-2">
          <Button variant="outline" onClick={() => onOpenChange(false)} disabled={saving}>
            Cancel
          </Button>
          <Button onClick={handleSubmit} disabled={saving}>
            {saving ? 'Saving…' : isEdit ? 'Save Changes' : 'Record Payment'}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

// ─── Remove Payment Alert Dialog ──────────────────────────────────────────────

function RemovePaymentDialog({ open, onOpenChange, bill, paymentId, onSuccess }) {
  const [removing, setRemoving] = useState(false);

  async function handleConfirm() {
    setRemoving(true);
    try {
      await api.deletePayment(paymentId);
      toast.success('Payment removed');
      onOpenChange(false);
      onSuccess?.();
    } catch (err) {
      toast.error(err.message);
    } finally {
      setRemoving(false);
    }
  }

  return (
    <AlertDialog open={open} onOpenChange={onOpenChange}>
      <AlertDialogContent>
        <AlertDialogHeader>
          <AlertDialogTitle>Remove payment?</AlertDialogTitle>
          <AlertDialogDescription>
            Removing this payment will mark{' '}
            <strong className="text-foreground">{bill?.name}</strong>{' '}
            as unpaid. The bill itself will not be deleted.
          </AlertDialogDescription>
        </AlertDialogHeader>
        <AlertDialogFooter>
          <AlertDialogCancel disabled={removing}>Cancel</AlertDialogCancel>
          <AlertDialogAction
            className={buttonVariants({ variant: 'destructive' })}
            onClick={handleConfirm}
            disabled={removing}
          >
            {removing ? 'Removing…' : 'Remove Payment'}
          </AlertDialogAction>
        </AlertDialogFooter>
      </AlertDialogContent>
    </AlertDialog>
  );
}

// ─── Bill Form stub ───────────────────────────────────────────────────────────

function openBillForm(bill) {
  // TODO: replace with shared BillFormDialog extracted from BillsPage
  console.log('[BillFormDialog] Edit bill:', bill);
}

// ─── Row Actions Dropdown ─────────────────────────────────────────────────────

function RowActions({ row, payInputRef, onRefresh }) {
  const [payDialogOpen,    setPayDialogOpen]    = useState(false);
  const [editDialogOpen,   setEditDialogOpen]   = useState(false);
  const [removeDialogOpen, setRemoveDialogOpen] = useState(false);

  const isPaid = row.status === 'paid' || row.status === 'autodraft';
  const latestPayment = row.payments?.length
    ? [...row.payments].sort((a, b) => b.paid_date.localeCompare(a.paid_date))[0]
    : null;

  async function handleQuickPay() {
    const raw    = payInputRef?.current?.value ?? String(row.expected_amount ?? '');
    const amount = parseFloat(raw);
    if (isNaN(amount) || amount <= 0) {
      toast.error('Enter a valid amount');
      return;
    }
    try {
      await api.quickPay({ bill_id: row.id, amount, paid_date: todayStr() });
      toast.success(`Paid ${fmt(amount)} for ${row.name}`);
      onRefresh();
    } catch (err) {
      toast.error(err.message);
    }
  }

  return (
    <>
      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <Button
            variant="ghost"
            size="icon"
            className="h-8 w-8 opacity-0 group-hover:opacity-100 transition-opacity"
          >
            <MoreHorizontal className="h-4 w-4" />
            <span className="sr-only">Row actions</span>
          </Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent align="end">
          {!isPaid ? (
            <>
              <DropdownMenuItem onSelect={handleQuickPay}>
                Quick Pay
              </DropdownMenuItem>
              <DropdownMenuItem onSelect={() => setPayDialogOpen(true)}>
                Record Payment…
              </DropdownMenuItem>
            </>
          ) : (
            <>
              <DropdownMenuItem onSelect={() => setEditDialogOpen(true)}>
                Edit Payment…
              </DropdownMenuItem>
              <DropdownMenuItem
                destructive
                onSelect={() => setRemoveDialogOpen(true)}
              >
                Remove Payment…
              </DropdownMenuItem>
            </>
          )}
          <DropdownMenuSeparator />
          <DropdownMenuItem onSelect={() => openBillForm(row)}>
            Edit Bill…
          </DropdownMenuItem>
        </DropdownMenuContent>
      </DropdownMenu>

      {/* Record Payment dialog (unpaid) */}
      <PaymentDialog
        open={payDialogOpen}
        onOpenChange={setPayDialogOpen}
        bill={row}
        payment={null}
        onSuccess={onRefresh}
      />

      {/* Edit Payment dialog (paid) */}
      <PaymentDialog
        open={editDialogOpen}
        onOpenChange={setEditDialogOpen}
        bill={row}
        payment={latestPayment}
        onSuccess={onRefresh}
      />

      {/* Remove Payment alert dialog */}
      <RemovePaymentDialog
        open={removeDialogOpen}
        onOpenChange={setRemoveDialogOpen}
        bill={row}
        paymentId={latestPayment?.id}
        onSuccess={onRefresh}
      />
    </>
  );
}

// ─── Bill Row ─────────────────────────────────────────────────────────────────

function BillRow({ row, onRefresh }) {
  const payInputRef = useRef(null);
  const isPaid      = row.status === 'paid' || row.status === 'autodraft';

  return (
    <TableRow className="group border-b border-border/50 last:border-0 hover:bg-muted/30 transition-colors duration-150">
      {/* Bill name + category */}
      <TableCell className="px-6 py-4">
        <div className="flex items-center gap-2.5">
          {row.autopay_enabled && (
            <span
              className="h-1.5 w-1.5 rounded-full bg-amber-400 shrink-0"
              title="Autopay"
            />
          )}
          <div>
            <p className="font-medium text-sm">{row.name}</p>
            {row.category_name && (
              <p className="text-xs text-muted-foreground mt-0.5">{row.category_name}</p>
            )}
          </div>
        </div>
      </TableCell>

      {/* Due date */}
      <TableCell className="px-6 py-4 w-24">
        <span className="text-sm text-muted-foreground">{fmtDate(row.due_date)}</span>
      </TableCell>

      {/* Expected */}
      <TableCell className="px-6 py-4 w-28 text-right">
        <span className="font-mono text-sm tabular-nums text-muted-foreground">
          {fmt(row.expected_amount)}
        </span>
      </TableCell>

      {/* Paid Date */}
      <TableCell className="px-6 py-4 w-28">
        {row.last_paid_date ? (
          <span className="text-sm tabular-nums text-emerald-500">
            {fmtDate(row.last_paid_date)}
          </span>
        ) : (
          <span className="text-sm text-muted-foreground/40">—</span>
        )}
      </TableCell>

      {/* Paid — input for unpaid, amount for paid */}
      <TableCell className="px-6 py-4 w-32 text-right">
        {isPaid ? (
          <span className="font-mono text-sm tabular-nums text-emerald-500 font-medium">
            {fmt(row.total_paid)}
          </span>
        ) : (
          <Input
            ref={payInputRef}
            type="number"
            step="0.01"
            min="0"
            className="h-8 w-24 text-right font-mono text-sm ml-auto"
            defaultValue={row.expected_amount}
          />
        )}
      </TableCell>

      {/* Status */}
      <TableCell className="px-6 py-4 w-32">
        <StatusChip status={row.status} />
      </TableCell>

      {/* Actions */}
      <TableCell className="px-6 py-4 w-12 text-right">
        <RowActions row={row} payInputRef={payInputRef} onRefresh={onRefresh} />
      </TableCell>
    </TableRow>
  );
}

// ─── Bucket Section ───────────────────────────────────────────────────────────

function BucketSection({ title, rows, paidAmount, totalAmount, loading, onRefresh }) {
  return (
    <div className="mb-3 mt-10 first:mt-0">
      {/* Floating bucket header — no card wrapper */}
      <div className="flex items-baseline justify-between mb-3">
        <h2 className="text-xs font-bold uppercase tracking-widest text-muted-foreground">
          {title}
        </h2>
        {!loading && rows.length > 0 && (
          <span className="text-xs tabular-nums text-muted-foreground">
            {fmt(paidAmount)} paid of {fmt(totalAmount)}
          </span>
        )}
      </div>

      {/* Table wrapped in card */}
      <div className="bg-card rounded-xl border border-border shadow-sm overflow-hidden mb-6">
        <Table>
          <TableHeader className="bg-muted/40 border-b border-border">
            <TableRow className="hover:bg-transparent border-0">
              <TableHead className="px-6 py-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                Bill
              </TableHead>
              <TableHead className="px-6 py-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground w-24">
                Due
              </TableHead>
              <TableHead className="px-6 py-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground w-28 text-right">
                Expected
              </TableHead>
              <TableHead className="px-6 py-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground w-28">
                Paid Date
              </TableHead>
              <TableHead className="px-6 py-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground w-32 text-right">
                Paid
              </TableHead>
              <TableHead className="px-6 py-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground w-32">
                Status
              </TableHead>
              <TableHead className="px-6 py-3 w-12" />
            </TableRow>
          </TableHeader>
          <TableBody>
            {loading ? (
              [1, 2, 3].map((i) => (
                <TableRow key={i} className="border-b border-border/50">
                  <TableCell className="px-6 py-4" colSpan={7}>
                    <div
                      className="h-4 rounded-md bg-muted/60 animate-pulse"
                      style={{ width: `${60 + i * 10}%` }}
                    />
                  </TableCell>
                </TableRow>
              ))
            ) : rows.length === 0 ? (
              <TableRow>
                <TableCell colSpan={7} className="py-16 text-center">
                  <div className="flex flex-col items-center gap-2">
                    <ReceiptText className="h-8 w-8 text-muted-foreground/40" />
                    <p className="text-sm text-muted-foreground">No bills for this period</p>
                    <a href="/bills" className="text-xs text-primary hover:underline">
                      Add a bill →
                    </a>
                  </div>
                </TableCell>
              </TableRow>
            ) : (
              rows.map((row) => (
                <BillRow key={row.id} row={row} onRefresh={onRefresh} />
              ))
            )}
          </TableBody>
        </Table>
      </div>
    </div>
  );
}

// ─── TrackerPage ──────────────────────────────────────────────────────────────

export default function TrackerPage() {
  const now = new Date();
  const [year,    setYear]    = useState(now.getFullYear());
  const [month,   setMonth]   = useState(now.getMonth() + 1);
  const [data,    setData]    = useState(null);
  const [loading, setLoading] = useState(true);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const res = await api.tracker(year, month);
      setData(res);
    } catch (err) {
      toast.error(err.message);
    } finally {
      setLoading(false);
    }
  }, [year, month]);

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

  function navigate(direction) {
    if (direction === -1) {
      if (month === 1) { setYear((y) => y - 1); setMonth(12); }
      else setMonth((m) => m - 1);
    } else {
      if (month === 12) { setYear((y) => y + 1); setMonth(1); }
      else setMonth((m) => m + 1);
    }
  }

  function goToToday() {
    const t = new Date();
    setYear(t.getFullYear());
    setMonth(t.getMonth() + 1);
  }

  const rows    = data?.rows    ?? [];
  const summary = data?.summary ?? {};

  const isCurrentMonth = year === now.getFullYear() && month === now.getMonth() + 1;

  const paidCount    = rows.filter((r) => r.status === 'paid' || r.status === 'autodraft').length;
  const overdueCount = rows.filter((r) => r.status === 'late' || r.status === 'missed').length;
  const allPaid      = rows.length > 0 && paidCount === rows.length;

  const bucket1  = rows.filter((r) => r.bucket === '1st');
  const bucket15 = rows.filter((r) => r.bucket === '15th');

  function bucketPaid(bucket) {
    return bucket.reduce((sum, r) => {
      const isPaid = r.status === 'paid' || r.status === 'autodraft';
      return sum + (isPaid ? (r.total_paid || 0) : 0);
    }, 0);
  }
  function bucketTotal(bucket) {
    return bucket.reduce((sum, r) => sum + (r.expected_amount || 0), 0);
  }

  return (
    <div>
      {/* ── Page Header — floats on page background, no card ── */}
      <div className="flex items-center justify-between mb-8">
        <div>
          <h1 className="text-2xl font-bold tracking-tight">
            {MONTH_NAMES[month - 1]} {year}
          </h1>
          <p className="text-sm text-muted-foreground mt-0.5">Monthly overview</p>
        </div>
        <div className="flex items-center gap-2">
          <Button
            variant="ghost"
            size="icon"
            className="h-8 w-8"
            onClick={() => navigate(-1)}
            aria-label="Previous month"
          >
            <ChevronLeft className="h-4 w-4" />
          </Button>
          <Button
            variant="ghost"
            size="icon"
            className="h-8 w-8"
            onClick={() => navigate(1)}
            aria-label="Next month"
          >
            <ChevronRight className="h-4 w-4" />
          </Button>
          {!isCurrentMonth && (
            <Button variant="outline" size="sm" onClick={goToToday}>
              Today
            </Button>
          )}
        </div>
      </div>

      {/* ── Summary Stat Tiles ── */}
      <div className="grid grid-cols-4 gap-4 mb-8">
        {/* Total Expected */}
        <div className="bg-card rounded-xl border border-border p-6 shadow-sm">
          <p className="text-xs font-semibold uppercase tracking-widest text-muted-foreground mb-3">
            Total Expected
          </p>
          <p className="text-3xl font-bold tracking-tight tabular-nums">
            {fmt(summary.total_expected)}
          </p>
          <p className="text-sm text-muted-foreground mt-1.5">
            {rows.length} bill{rows.length !== 1 ? 's' : ''} this month
          </p>
        </div>

        {/* Paid */}
        <div className="bg-card rounded-xl border border-border p-6 shadow-sm">
          <p className="text-xs font-semibold uppercase tracking-widest text-muted-foreground mb-3">
            Paid
          </p>
          <p className={cn('text-3xl font-bold tracking-tight tabular-nums', allPaid && 'text-emerald-500')}>
            {fmt(summary.total_paid)}
          </p>
          <p className="text-sm text-muted-foreground mt-1.5">
            {paidCount} of {rows.length} paid
          </p>
        </div>

        {/* Remaining */}
        <div className="bg-card rounded-xl border border-border p-6 shadow-sm">
          <p className="text-xs font-semibold uppercase tracking-widest text-muted-foreground mb-3">
            Remaining
          </p>
          <p className="text-3xl font-bold tracking-tight tabular-nums">
            {fmt(summary.remaining)}
          </p>
          <p className={cn('text-sm mt-1.5', overdueCount > 0 ? 'text-orange-400' : 'text-muted-foreground')}>
            {overdueCount > 0
              ? `includes ${fmt(summary.overdue)} overdue`
              : `${rows.length - paidCount} unpaid`}
          </p>
        </div>

        {/* Overdue */}
        <div className="bg-card rounded-xl border border-border p-6 shadow-sm">
          <p className="text-xs font-semibold uppercase tracking-widest text-muted-foreground mb-3">
            Overdue
          </p>
          <p className={cn('text-3xl font-bold tracking-tight tabular-nums', overdueCount > 0 ? 'text-red-500' : 'text-muted-foreground')}>
            {fmt(summary.overdue)}
          </p>
          <p className="text-sm text-muted-foreground mt-1.5">
            {overdueCount > 0
              ? `${overdueCount} bill${overdueCount !== 1 ? 's' : ''} overdue`
              : 'All clear'}
          </p>
        </div>
      </div>

      {/* ── Bucket Sections ── */}
      <BucketSection
        title="1st – 14th"
        rows={bucket1}
        paidAmount={bucketPaid(bucket1)}
        totalAmount={bucketTotal(bucket1)}
        loading={loading}
        onRefresh={load}
      />
      <BucketSection
        title="15th – 31st"
        rows={bucket15}
        paidAmount={bucketPaid(bucket15)}
        totalAmount={bucketTotal(bucket15)}
        loading={loading}
        onRefresh={load}
      />
    </div>
  );
}
