import { useState } from 'react';
import type { Expense, Person } from '@splint/shared';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
  Select,
  SelectTrigger,
  SelectValue,
  SelectContent,
  SelectItem,
} from '@/components/ui/select';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from '@/components/ui/dialog';
import { Checkbox } from '@/components/ui/checkbox';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
import { Item, ItemContent, ItemTitle, ItemDescription, ItemActions } from '@/components/ui/item';
import { Badge } from '@/components/ui/badge';
import { Pencil, Trash2 } from 'lucide-react';

// ── Types ───────────────────────────────────────────────────────────────────

interface ExpensesListProps {
  expenses: Expense[];
  people: Person[];
  onEditExpense: (expense: Expense) => void;
  onRequestAdd: () => void;
  onDelete: (id: string) => Promise<void>;
  saving: boolean;
}

// ── ExpenseModal ────────────────────────────────────────────────────────────

interface ExpenseModalProps {
  people: Person[];
  editingExpense: Expense | null;
  onSave: (fields: {
    paidBy: string;
    amount: number;
    description: string;
    splitAmong: string[];
  }) => Promise<void>;
  onClose: () => void;
  saving: boolean;
}

export function ExpenseModal({
  people,
  editingExpense,
  onSave,
  onClose,
  saving,
}: ExpenseModalProps) {
  const [form, setForm] = useState({
    description: editingExpense?.description ?? '',
    amount: editingExpense ? (editingExpense.amount / 100).toFixed(2) : '',
    paidBy: editingExpense?.paidBy ?? '',
    splitAmong: editingExpense?.splitAmong ?? ([] as string[]),
  });
  const [errors, setErrors] = useState<Record<string, string>>({});

  function validate(): boolean {
    const next: Record<string, string> = {};
    if (!form.description.trim()) next.description = 'Description is required.';
    if (!form.amount || parseFloat(form.amount) <= 0)
      next.amount = 'Amount must be greater than zero.';
    if (!form.paidBy) next.paidBy = 'Select who paid.';
    if (form.splitAmong.length === 0)
      next.splitAmong = 'Select at least one person to split with.';
    setErrors(next);
    return Object.keys(next).length === 0;
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!validate()) return;
    try {
      await onSave({
        description: form.description.trim(),
        amount: Math.round(parseFloat(form.amount) * 100),
        paidBy: form.paidBy,
        splitAmong: form.splitAmong,
      });
      onClose();
    } catch (err) {
      setErrors({
        _form: err instanceof Error ? err.message : 'Failed to save expense.',
      });
    }
  }

  return (
    <Dialog open={true} onOpenChange={(open) => !open && onClose()}>
      <DialogContent aria-label={editingExpense ? 'Edit expense' : 'Add expense'}>
        <DialogHeader>
          <DialogTitle>
            {editingExpense ? 'Edit Expense' : 'Add Expense'}
          </DialogTitle>
        </DialogHeader>
        <form onSubmit={handleSubmit} className="space-y-4">
          <div className="space-y-2">
            <Label htmlFor="exp-desc">Description</Label>
            <Input
              id="exp-desc"
              type="text"
              value={form.description}
              onChange={(e) => setForm({ ...form, description: e.target.value })}
              placeholder="Dinner, groceries..."
              autoFocus
            />
            {errors.description && (
              <p className="text-xs text-destructive" role="alert">
                {errors.description}
              </p>
            )}
          </div>
          <div className="space-y-2">
            <Label htmlFor="exp-amount">Amount ($)</Label>
            <Input
              id="exp-amount"
              type="number"
              step="0.01"
              value={form.amount}
              onChange={(e) => setForm({ ...form, amount: e.target.value })}
              placeholder="0.00"
            />
            {errors.amount && (
              <p className="text-xs text-destructive" role="alert">
                {errors.amount}
              </p>
            )}
          </div>
          <div className="space-y-2">
            <Label htmlFor="exp-paidby">Paid by</Label>
            <Select
              value={form.paidBy}
              onValueChange={(value) => setForm({ ...form, paidBy: value })}
            >
              <SelectTrigger id="exp-paidby" className="w-full">
                <SelectValue placeholder="Select..." />
              </SelectTrigger>
              <SelectContent>
                {people.map((p) => (
                  <SelectItem key={p.id} value={p.id}>
                    {p.name}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            {errors.paidBy && (
              <p className="text-xs text-destructive" role="alert">
                {errors.paidBy}
              </p>
            )}
          </div>
          <div className="space-y-2">
            <Label>Split among</Label>
            <div className="flex flex-wrap gap-2" role="group" aria-label="Split among">
              {people.map((p) => (
                <label
                  key={p.id}
                  className="flex items-center gap-1.5 cursor-pointer"
                >
                  <Checkbox
                    checked={form.splitAmong.includes(p.id)}
                    onCheckedChange={(checked) => {
                      const next = checked
                        ? [...form.splitAmong, p.id]
                        : form.splitAmong.filter((x) => x !== p.id);
                      setForm({ ...form, splitAmong: next });
                    }}
                  />
                  <span className="text-xs">{p.name}</span>
                </label>
              ))}
            </div>
            {errors.splitAmong && (
              <p className="text-xs text-destructive" role="alert">
                {errors.splitAmong}
              </p>
            )}
          </div>
          {errors._form && (
            <p className="text-xs text-destructive" role="alert">
              {errors._form}
            </p>
          )}
          <DialogFooter>
            <Button type="submit" disabled={saving}>
              {editingExpense ? 'Save Changes' : 'Add Expense'}
            </Button>
            <Button type="button" variant="outline" onClick={onClose}>
              Cancel
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}

// ── ExpensesList ────────────────────────────────────────────────────────────

export function ExpensesList({
  expenses,
  people,
  onEditExpense,
  onRequestAdd,
  onDelete,
  saving,
}: ExpensesListProps) {
  const [deleteExpenseId, setDeleteExpenseId] = useState<string | null>(null);
  const isEmpty = expenses.length === 0;

  async function handleDelete(id: string) {
    try {
      await onDelete(id);
      setDeleteExpenseId(null);
    } catch {
      /* delete error is silent */
    }
  }

  return (
    <Card>
      <CardHeader className="flex flex-row items-center justify-between">
        <CardTitle>Expenses</CardTitle>
        <Button size="sm" onClick={onRequestAdd}>
          + Add
        </Button>
      </CardHeader>
      <CardContent>
        {isEmpty ? (
          <p className="text-xs text-muted-foreground text-center py-4">
            No expenses yet. Add one to get started!
          </p>
        ) : (
          <div role="list">
            {expenses.map((e) => {
              const payer = people.find((p) => p.id === e.paidBy);
              const splitNames = e.splitAmong
                .map((pid) => people.find((p) => p.id === pid)?.name ?? '?')
                .join(', ');

              if (deleteExpenseId === e.id) {
                return (
                  <div
                    key={e.id}
                    className="flex flex-col gap-2 py-3 border-b border-border last:border-0"
                  >
                    <p className="text-xs text-muted-foreground">
                      Delete &quot;<strong>{e.description}</strong>&quot; ($
                      {(e.amount / 100).toFixed(2)})?
                    </p>
                    <div className="flex gap-2">
                      <Button
                        variant="destructive"
                        size="sm"
                        onClick={() => handleDelete(e.id)}
                      >
                        Delete
                      </Button>
                      <Button
                        variant="outline"
                        size="sm"
                        onClick={() => setDeleteExpenseId(null)}
                      >
                        Keep
                      </Button>
                    </div>
                  </div>
                );
              }

              return (
                <Item key={e.id} variant="outline" size="xs" role="listitem">
                  <ItemContent>
                    <ItemTitle>
                      <span className="font-medium truncate">{e.description}</span>
                      <Badge variant="default" className="shrink-0 bg-primary/15 text-primary hover:bg-primary/20">
                        ${(e.amount / 100).toFixed(2)}
                      </Badge>
                    </ItemTitle>
                    <ItemDescription>
                      Paid by {payer?.name ?? 'unknown'} · {splitNames}
                    </ItemDescription>
                  </ItemContent>
                  <ItemActions>
                    <Button
                      variant="ghost"
                      size="icon-sm"
                      onClick={() => onEditExpense(e)}
                      aria-label={`Edit ${e.description}`}
                    >
                      <Pencil />
                    </Button>
                    <Button
                      variant="ghost"
                      size="icon-sm"
                      onClick={() => setDeleteExpenseId(e.id)}
                      aria-label={`Delete ${e.description}`}
                    >
                      <Trash2 className="text-destructive" />
                    </Button>
                  </ItemActions>
                </Item>
              );
            })}
          </div>
        )}
      </CardContent>
    </Card>
  );
}
