import { useState, useEffect, useMemo } from 'react';
import { CheckCircle2, Loader2, Link2, Search, Plus } from 'lucide-react';
import { cn } from '@/lib/utils';
import { formatCentsUSD } from '@/lib/money';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import type { BankTransaction, Bill } from '@/types';

export function transactionDate(tx: BankTransaction | null | undefined): string {
  return tx?.posted_date || String(tx?.transacted_at || '').slice(0, 10) || '—';
}

export function transactionTitle(tx: BankTransaction | null | undefined): string {
  return tx?.payee || tx?.description || tx?.memo || 'Transaction';
}

export function formatTransactionAmount(
  amount: Parameters<typeof formatCentsUSD>[0],
  currency = 'USD',
) {
  return formatCentsUSD(amount, { signed: true, currency });
}

interface MatchBillDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  transaction: BankTransaction | null;
  bills: Bill[];
  onConfirm: (billId: number | string) => void;
  loading?: boolean;
  onCreateBill?: (transaction: BankTransaction | null, query?: string) => void;
}

export function MatchBillDialog({
  open,
  onOpenChange,
  transaction,
  bills,
  onConfirm,
  loading,
  onCreateBill,
}: MatchBillDialogProps) {
  const [query, setQuery] = useState('');
  const [selectedBillId, setSelectedBillId] = useState('');

  useEffect(() => {
    if (open) {
      setQuery('');
      setSelectedBillId(transaction?.matched_bill_id ? String(transaction.matched_bill_id) : '');
    }
  }, [open, transaction?.id, transaction?.matched_bill_id]);

  const filteredBills = useMemo(() => {
    const q = query.trim().toLowerCase();
    if (!q) return bills.slice(0, 40);
    return bills
      .filter((bill) =>
        String(bill.name || '')
          .toLowerCase()
          .includes(q),
      )
      .slice(0, 40);
  }, [bills, query]);

  const selectedBill = bills.find((bill) => String(bill.id) === String(selectedBillId));
  const af = transaction?.advisory_filter as { confidence?: string } | undefined;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-2xl">
        <DialogHeader>
          <DialogTitle>Match Transaction</DialogTitle>
          <DialogDescription>
            Choose the bill this transaction paid. Nothing changes until you confirm.
          </DialogDescription>
        </DialogHeader>

        {transaction && (
          <div className="rounded-lg border border-border/60 bg-muted/25 p-3">
            <div className="flex flex-wrap items-center justify-between gap-2">
              <div className="min-w-0">
                <p className="truncate text-sm font-medium">{transactionTitle(transaction)}</p>
                <p className="mt-0.5 text-xs text-muted-foreground">
                  {transactionDate(transaction)} ·{' '}
                  {transaction.source_label || transaction.source_type_label || 'Transaction'}
                </p>
              </div>
              <p
                className={cn(
                  'text-sm font-semibold tabular-nums',
                  Number(transaction.amount) < 0 ? 'text-destructive' : 'text-emerald-600',
                )}
              >
                {formatTransactionAmount(transaction.amount, transaction.currency ?? undefined)}
              </p>
            </div>
            {transaction.description &&
              transaction.description !== transactionTitle(transaction) && (
                <p className="mt-2 text-xs text-muted-foreground">{transaction.description}</p>
              )}
          </div>
        )}

        <div className="space-y-3">
          <label className="space-y-1.5">
            <span className="text-xs font-medium text-muted-foreground">Find bill</span>
            <div className="relative">
              <Search className="pointer-events-none absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
              <Input
                value={query}
                onChange={(e) => setQuery(e.target.value)}
                placeholder="Search bills"
                className="pl-8"
              />
            </div>
          </label>

          <div className="max-h-72 overflow-y-auto rounded-lg border border-border/60">
            {filteredBills.length === 0 ? (
              <div className="flex flex-col items-center gap-3 px-4 py-8 text-center">
                <p className="text-sm text-muted-foreground">No bills found.</p>
                {onCreateBill &&
                  (() => {
                    const label = query.trim()
                      ? `Create "${query.trim()}" as a new bill`
                      : 'Create a new bill';
                    if (af?.confidence === 'high') {
                      return (
                        <span className="text-xs text-muted-foreground">
                          Probably not a bill ·{' '}
                          <button
                            type="button"
                            className="underline hover:text-foreground transition-colors"
                            onClick={() => {
                              onOpenChange(false);
                              onCreateBill(transaction, query.trim() || undefined);
                            }}
                          >
                            {label}
                          </button>
                        </span>
                      );
                    }
                    return (
                      <button
                        type="button"
                        onClick={() => {
                          onOpenChange(false);
                          onCreateBill(transaction, query.trim() || undefined);
                        }}
                        className={cn(
                          'flex items-center gap-1.5 text-xs hover:underline',
                          af?.confidence === 'medium' ? 'text-muted-foreground' : 'text-primary',
                        )}
                      >
                        <Plus className="h-3.5 w-3.5" />
                        {label}
                      </button>
                    );
                  })()}
              </div>
            ) : (
              <div className="divide-y divide-border/40">
                {filteredBills.map((bill) => (
                  <button
                    key={bill.id}
                    type="button"
                    onClick={() => setSelectedBillId(String(bill.id))}
                    className={cn(
                      'flex w-full items-center justify-between gap-3 px-4 py-3 text-left transition-colors hover:bg-muted/30',
                      String(selectedBillId) === String(bill.id) && 'bg-primary/5',
                    )}
                  >
                    <div className="min-w-0">
                      <p className="truncate text-sm font-medium">{bill.name}</p>
                      <p className="mt-0.5 text-xs text-muted-foreground">
                        Due day {bill.due_day ?? '—'} · expected $
                        {Number(bill.expected_amount || 0).toFixed(2)}
                      </p>
                    </div>
                    {String(selectedBillId) === String(bill.id) && (
                      <CheckCircle2 className="h-4 w-4 shrink-0 text-primary" />
                    )}
                  </button>
                ))}
              </div>
            )}
          </div>
        </div>

        <DialogFooter className="gap-2">
          {onCreateBill &&
            (() => {
              if (af?.confidence === 'high') {
                return (
                  <span className="mr-auto flex items-center gap-2 text-xs text-muted-foreground">
                    Probably not a bill
                    <button
                      type="button"
                      className="underline hover:text-foreground transition-colors"
                      onClick={() => {
                        onOpenChange(false);
                        onCreateBill(transaction);
                      }}
                    >
                      create anyway
                    </button>
                  </span>
                );
              }
              return (
                <Button
                  type="button"
                  variant="ghost"
                  className={cn(
                    'mr-auto text-xs',
                    af?.confidence === 'medium'
                      ? 'text-muted-foreground/60 hover:text-muted-foreground'
                      : 'text-muted-foreground hover:text-foreground',
                  )}
                  onClick={() => {
                    onOpenChange(false);
                    onCreateBill(transaction);
                  }}
                >
                  <Plus className="h-3.5 w-3.5 mr-1.5" />
                  Create Bill
                </Button>
              );
            })()}
          <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button
            type="button"
            disabled={!selectedBill || loading}
            onClick={() => selectedBill && onConfirm(selectedBill.id)}
          >
            {loading ? (
              <>
                <Loader2 className="h-3.5 w-3.5 mr-1.5 animate-spin" />
                Matching…
              </>
            ) : (
              <>
                <Link2 className="h-3.5 w-3.5 mr-1.5" />
                Confirm Match
              </>
            )}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
