import { useState } from 'react';
import type { Person, LedgerData } from '@splint/shared';
import { computeBalances } from '@splint/shared';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
import { Item, ItemContent, ItemTitle, ItemDescription, ItemActions } from '@/components/ui/item';
import { Pencil, Trash2 } from 'lucide-react';

// ── Safety check ────────────────────────────────────────────────────────────

function canRemovePerson(
  personId: string,
  data: LedgerData,
  balances: Map<string, number>,
): { ok: true } | { ok: false; reason: string } {
  const balance = balances.get(personId) ?? 0;
  if (balance !== 0)
    return { ok: false, reason: 'Person has a non-zero balance — settle up first.' };
  const hasExpenses = data.expenses.some(
    (e) => e.paidBy === personId || e.splitAmong.includes(personId),
  );
  if (hasExpenses)
    return { ok: false, reason: 'Person is referenced by expenses — delete those first.' };
  const hasTransfers = data.transfers.some(
    (t) => t.from === personId || t.to === personId,
  );
  if (hasTransfers)
    return { ok: false, reason: 'Person is referenced by transfers — delete those first.' };
  return { ok: true };
}

// ── Props ───────────────────────────────────────────────────────────────────

interface PeopleListProps {
  people: Person[];
  expenses: LedgerData['expenses'];
  transfers: LedgerData['transfers'];
  onAdd: (name: string) => Promise<void>;
  onUpdate: (id: string, name: string) => Promise<void>;
  onRemove: (id: string) => Promise<void>;
  saving: boolean;
}

// ── Component ───────────────────────────────────────────────────────────────

export function PeopleList({
  people,
  expenses,
  transfers,
  onAdd,
  onUpdate,
  onRemove,
  saving,
}: PeopleListProps) {
  // ── Form state ──────────────────────────────────────────────────────────
  const [newPersonName, setNewPersonName] = useState('');
  const [personError, setPersonError] = useState('');
  const [editingPersonId, setEditingPersonId] = useState<string | null>(null);
  const [editPersonName, setEditPersonName] = useState('');
  const [deletePersonId, setDeletePersonId] = useState<string | null>(null);
  const [deletePersonError, setDeletePersonError] = useState('');

  // ── Derived ─────────────────────────────────────────────────────────────
  const balances = computeBalances(
    people.map((p) => p.id),
    expenses,
    transfers,
  );
  const maxAbsBalance = Math.max(
    1,
    ...Array.from(balances.values()).map(Math.abs),
  );

  const isEmpty = people.length === 0;

  // ── Handlers ────────────────────────────────────────────────────────────

  async function handleAddPerson(e: React.FormEvent) {
    e.preventDefault();
    const name = newPersonName.trim();
    if (!name) {
      setPersonError('Name cannot be empty.');
      return;
    }
    setPersonError('');
    try {
      await onAdd(name);
      setNewPersonName('');
    } catch (err) {
      setPersonError(
        err instanceof Error ? err.message : 'Failed to add person.',
      );
    }
  }

  function startEditPerson(id: string, current: string) {
    setEditingPersonId(id);
    setEditPersonName(current);
  }

  async function handleSavePersonName() {
    if (!editingPersonId) return;
    const name = editPersonName.trim();
    if (!name) return;
    try {
      await onUpdate(editingPersonId, name);
      setEditingPersonId(null);
    } catch (err) {
      setPersonError(
        err instanceof Error ? err.message : 'Failed to rename person.',
      );
    }
  }

  function cancelEditPerson() {
    setEditingPersonId(null);
  }

  function confirmRemove(personId: string) {
    const check = canRemovePerson(
      personId,
      { people, expenses, transfers },
      balances,
    );
    if (!check.ok) {
      setDeletePersonError(check.reason);
      setTimeout(() => setDeletePersonError(''), 4000);
      return;
    }
    setDeletePersonId(personId);
  }

  async function handleRemovePerson() {
    if (!deletePersonId) return;
    try {
      await onRemove(deletePersonId);
      setDeletePersonId(null);
    } catch (err) {
      setPersonError(
        err instanceof Error ? err.message : 'Failed to remove person.',
      );
    }
  }

  // ── Render ──────────────────────────────────────────────────────────────

  return (
    <Card>
      <CardHeader>
        <CardTitle>People</CardTitle>
      </CardHeader>
      <CardContent>
        {isEmpty ? (
          <p className="text-xs text-muted-foreground py-4">No people yet.</p>
        ) : (
          people.map((p) => {
            const balance = balances.get(p.id) ?? 0;
            const absBal = Math.abs(balance);
            const barWidth =
              maxAbsBalance > 0 ? (absBal / maxAbsBalance) * 100 : 0;

            // ── Inline edit mode ───────────────────────────────────────────
            if (editingPersonId === p.id) {
              return (
                <div
                  key={p.id}
                  className="flex flex-col gap-2 py-3 border-b border-border last:border-0"
                >
                  <form
                    className="flex gap-2"
                    onSubmit={(e) => {
                      e.preventDefault();
                      handleSavePersonName();
                    }}
                  >
                    <Input
                      type="text"
                      value={editPersonName}
                      onChange={(e) => setEditPersonName(e.target.value)}
                      autoFocus
                      className="flex-1"
                      aria-label="Edit person name"
                    />
                    <Button type="submit" variant="default" size="sm">
                      Save
                    </Button>
                    <Button
                      type="button"
                      variant="outline"
                      size="sm"
                      onClick={cancelEditPerson}
                    >
                      Cancel
                    </Button>
                  </form>
                </div>
              );
            }

            // ── Inline delete confirmation ─────────────────────────────────
            if (deletePersonId === p.id) {
              return (
                <div
                  key={p.id}
                  className="flex flex-col gap-2 py-3 border-b border-border last:border-0"
                >
                  <p className="text-xs text-muted-foreground">
                    Remove <strong>{p.name}</strong>?
                  </p>
                  <div className="flex gap-2">
                    <Button
                      variant="destructive"
                      size="sm"
                      onClick={handleRemovePerson}
                    >
                      Remove
                    </Button>
                    <Button
                      variant="outline"
                      size="sm"
                      onClick={() => setDeletePersonId(null)}
                    >
                      Keep
                    </Button>
                  </div>
                </div>
              );
            }

            // ── Default display ────────────────────────────────────────────
            let balanceLabel: string;
            let balanceClass: string;
            if (balance === 0) {
              balanceLabel = 'settled';
              balanceClass = '';
            } else if (balance > 0) {
              balanceLabel = `+$${(balance / 100).toFixed(2)}`;
              balanceClass = 'text-green-400';
            } else {
              balanceLabel = `-$${(-balance / 100).toFixed(2)}`;
              balanceClass = 'text-destructive';
            }

            return (
              <Item key={p.id} variant={balance === 0 ? 'default' : 'outline'} size="xs">
                <ItemContent>
                  <ItemTitle>
                    <span className="font-medium">{p.name}</span>
                    <span className={`font-medium shrink-0 ml-auto ${
                      balance > 0 ? 'text-[var(--color-success)]' :
                      balance < 0 ? 'text-destructive' :
                      'text-muted-foreground'
                    }`}>
                      {balanceLabel}
                    </span>
                  </ItemTitle>
                  {balance !== 0 && (
                    <div className="balance-bar mt-0.5" style={{ width: '100%' }}>
                      <div
                        className={`balance-bar-fill ${balance > 0 ? 'credit' : 'owed'}`}
                        style={{ width: `${Math.max(barWidth, 4)}%` }}
                      />
                    </div>
                  )}
                </ItemContent>
                <ItemActions>
                  <Button
                    variant="ghost"
                    size="icon-sm"
                    onClick={() => startEditPerson(p.id, p.name)}
                    aria-label={`Rename ${p.name}`}
                  >
                    <Pencil />
                  </Button>
                  <Button
                    variant="ghost"
                    size="icon-sm"
                    onClick={() => confirmRemove(p.id)}
                    aria-label={`Remove ${p.name}`}
                  >
                    <Trash2 className="text-destructive" />
                  </Button>
                </ItemActions>
              </Item>
            );
          })
        )}

        {/* Add person form */}
        <form className="flex gap-2 mt-4" onSubmit={handleAddPerson}>
          <Input
            type="text"
            value={newPersonName}
            onChange={(e) => {
              setNewPersonName(e.target.value);
              setPersonError('');
            }}
            placeholder="Add person..."
            className="flex-1"
            aria-label="New person name"
          />
          <Button type="submit" size="sm" disabled={saving}>
            Add
          </Button>
        </form>
        {personError && (
          <p className="text-xs text-destructive mt-2" role="alert">
            {personError}
          </p>
        )}
        {deletePersonError && (
          <p className="text-xs text-destructive mt-2" role="alert">
            {deletePersonError}
          </p>
        )}
      </CardContent>
    </Card>
  );
}
