"use client";

import React, { useEffect, useMemo, useState } from "react";
import { useParams, useRouter } from "next/navigation";
import { useAuth } from "@/hooks/useAuth";
import { apiFetch } from "@/lib/api";
import { useDismissingState } from "@/hooks/useDismissingState";
import type { EventCost, EventCostType, EventFinancials, CashupMethod } from "@/types";
import { Wallet, DollarSign, ClipboardCheck, FileBarChart } from "lucide-react";

const METHOD_LABELS: Record<CashupMethod, string> = { cash: "Cash", card: "Card", eft: "EFT", other: "Other" };
const METHODS: CashupMethod[] = ["cash", "card", "eft", "other"];
const ZAR_DENOMINATIONS = [200, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1];

function money(n: number | null | undefined): string {
  return `R${Number(n || 0).toFixed(2)}`;
}
function denomLabel(v: number): string {
  return v >= 1 ? `R${v}` : `${Math.round(v * 100)}c`;
}

type LineInput = { actualAmount: string; notes: string };

export default function EventCashupPage() {
  const params = useParams<{ id: string }>();
  const eventId = params.id;
  const router = useRouter();
  const { token } = useAuth();

  const [tab, setTab] = useState<"costs" | "reconciliation" | "report">("costs");
  const [data, setData] = useState<EventFinancials | null>(null);
  const [eventOptions, setEventOptions] = useState<{ id: string; name: string }[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useDismissingState<string | null>(null);
  const [busy, setBusy] = useState(false);

  const isClosed = data?.event?.cashupStatus === "closed";

  const load = async () => {
    if (!token || !eventId) return;
    setLoading(true);
    setError(null);
    try {
      const [financials, event] = await Promise.all([
        apiFetch<EventFinancials>(`/api/cashups/event/${eventId}`, { authToken: token }),
        apiFetch<any>(`/api/events/${eventId}`, { authToken: token })
      ]);
      setData(financials);
      setEventOptions((event.eventOptions || []).map((o: any) => ({ id: o.id, name: o.name })));
    } catch (e: any) {
      setError(e?.message || "Failed to load cashup data");
    } finally {
      setLoading(false);
    }
  };

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

  return (
    <div className="max-w-4xl mx-auto space-y-4">
      <div className="flex items-center justify-between gap-3 flex-wrap">
        <div className="flex items-center gap-3">
          <div className="w-10 h-10 rounded-xl bg-brand-50 flex items-center justify-center shrink-0">
            <Wallet className="w-5 h-5 text-brand-600" />
          </div>
          <div>
            <button className="text-xs text-brand-600 hover:underline" onClick={() => router.push("/dashboard/admin/cashup")}>← Back to cashup</button>
            <h1 className="text-xl font-semibold text-gray-900 mt-0.5">{data?.event?.title || "Event"} — Cashup</h1>
          </div>
        </div>
        <span className={"text-xs px-2 py-1 rounded-full font-medium " + (isClosed ? "bg-rose-50 text-rose-700" : "bg-emerald-50 text-emerald-700")}>
          {isClosed ? "Closed" : "Open"}
        </span>
      </div>

      {error && <div className="text-sm text-red-600 bg-red-50 border border-red-100 rounded p-2">{error}</div>}

      <div className="flex gap-2 border-b">
        <button className={"inline-flex items-center gap-1.5 px-3 py-2 text-sm " + (tab === "costs" ? "border-b-2 border-brand-600 text-brand-700 font-medium" : "text-gray-500")} onClick={() => setTab("costs")}><DollarSign className="w-4 h-4" />Costs</button>
        <button className={"inline-flex items-center gap-1.5 px-3 py-2 text-sm " + (tab === "reconciliation" ? "border-b-2 border-brand-600 text-brand-700 font-medium" : "text-gray-500")} onClick={() => setTab("reconciliation")}><ClipboardCheck className="w-4 h-4" />Reconciliation</button>
        <button className={"inline-flex items-center gap-1.5 px-3 py-2 text-sm " + (tab === "report" ? "border-b-2 border-brand-600 text-brand-700 font-medium" : "text-gray-500")} onClick={() => setTab("report")}><FileBarChart className="w-4 h-4" />Report</button>
      </div>

      {loading && <div className="text-sm text-gray-400">Loading…</div>}

      {!loading && data && tab === "costs" && (
        <CostsTab eventId={eventId} token={token || ""} costs={data.costs} eventOptions={eventOptions} isClosed={isClosed} onChanged={load} />
      )}

      {!loading && data && tab === "reconciliation" && (
        <ReconciliationTab
          eventId={eventId}
          token={token || ""}
          data={data}
          busy={busy}
          setBusy={setBusy}
          setError={setError}
          onChanged={load}
          onClosed={() => setTab("report")}
        />
      )}

      {!loading && data && tab === "report" && (
        <ReportTab eventId={eventId} token={token || ""} data={data} isClosed={isClosed} />
      )}
    </div>
  );
}

// ─── Costs tab ─────────────────────────────────────────────────────────────

function CostsTab({ eventId, token, costs, eventOptions, isClosed, onChanged }: {
  eventId: string; token: string; costs: EventCost[]; eventOptions: { id: string; name: string }[]; isClosed: boolean; onChanged: () => void;
}) {
  const [editingId, setEditingId] = useState<string | "new" | null>(null);
  const [label, setLabel] = useState("");
  const [costType, setCostType] = useState<EventCostType>("once_off");
  const [amount, setAmount] = useState("");
  const [eventOptionId, setEventOptionId] = useState("");
  const [paidFromMethod, setPaidFromMethod] = useState<"" | CashupMethod>("");
  const [notes, setNotes] = useState("");
  const [saving, setSaving] = useState(false);
  const [err, setErr] = useState<string | null>(null);

  const startNew = () => {
    setEditingId("new");
    setLabel(""); setCostType("once_off"); setAmount(""); setEventOptionId(""); setPaidFromMethod(""); setNotes("");
    setErr(null);
  };

  const startEdit = (c: EventCost) => {
    setEditingId(c.id);
    setLabel(c.label); setCostType(c.costType); setAmount(String(c.amount)); setEventOptionId(c.eventOptionId || ""); setPaidFromMethod(c.paidFromMethod || ""); setNotes(c.notes || "");
    setErr(null);
  };

  const cancel = () => setEditingId(null);

  const save = async () => {
    if (!label.trim()) { setErr("Label is required"); return; }
    if (!amount || isNaN(parseFloat(amount))) { setErr("Amount is required"); return; }
    if (costType === "per_item" && !eventOptionId) { setErr("Select a ticket type for per-item costs"); return; }
    setSaving(true);
    setErr(null);
    try {
      const body = { label: label.trim(), costType, amount: parseFloat(amount), eventOptionId: costType === "per_item" ? eventOptionId : null, paidFromMethod: paidFromMethod || null, notes: notes || null };
      if (editingId === "new") {
        await apiFetch(`/api/events/${eventId}/costs`, { method: "POST", authToken: token, body });
      } else {
        await apiFetch(`/api/costs/${editingId}`, { method: "PUT", authToken: token, body });
      }
      setEditingId(null);
      onChanged();
    } catch (e: any) {
      setErr(e?.message || "Failed to save cost");
    } finally {
      setSaving(false);
    }
  };

  const remove = async (id: string) => {
    if (!confirm("Delete this cost?")) return;
    try {
      await apiFetch(`/api/costs/${id}`, { method: "DELETE", authToken: token });
      onChanged();
    } catch (e: any) {
      alert(e?.message || "Failed to delete cost");
    }
  };

  const totalCosts = costs.reduce((sum, c) => sum + (c.total ?? c.amount), 0);

  return (
    <div className="bg-white border rounded-lg p-4 space-y-3">
      <div className="flex items-center justify-between">
        <div className="text-sm font-medium">Event costs</div>
        {!isClosed && editingId === null && (
          <button className="text-xs px-2 py-1 rounded bg-brand-600 text-white hover:bg-brand-700" onClick={startNew}>+ Add cost</button>
        )}
      </div>

      {isClosed && <div className="text-xs text-gray-500">This event is closed — costs can't be changed until it's reopened.</div>}

      <div className="overflow-auto">
        <table className="w-full text-sm min-w-[600px]">
          <thead>
            <tr className="text-left text-gray-500 border-b">
              <th className="py-1">Label</th>
              <th className="py-1">Type</th>
              <th className="py-1">Ticket type</th>
              <th className="py-1">Paid from</th>
              <th className="py-1 text-right">Amount</th>
              <th className="py-1 text-right">Total</th>
              {!isClosed && <th className="py-1"></th>}
            </tr>
          </thead>
          <tbody>
            {costs.map(c => (
              <tr key={c.id} className="border-b last:border-0">
                <td className="py-1.5">{c.label}</td>
                <td className="py-1.5">{c.costType === "once_off" ? "Once-off" : "Per item"}</td>
                <td className="py-1.5">{c.eventOption?.name || "—"}</td>
                <td className="py-1.5 capitalize">{c.paidFromMethod || "—"}</td>
                <td className="py-1.5 text-right">{money(c.amount)}</td>
                <td className="py-1.5 text-right font-medium">{money(c.total ?? c.amount)}</td>
                {!isClosed && (
                  <td className="py-1.5 text-right whitespace-nowrap">
                    <button className="text-xs text-brand-600 hover:underline mr-2" onClick={() => startEdit(c)}>Edit</button>
                    <button className="text-xs text-red-600 hover:underline" onClick={() => remove(c.id)}>Delete</button>
                  </td>
                )}
              </tr>
            ))}
            {costs.length === 0 && (
              <tr><td colSpan={7} className="py-3 text-gray-400 text-center">No costs added yet.</td></tr>
            )}
          </tbody>
          {costs.length > 0 && (
            <tfoot>
              <tr>
                <td colSpan={5} className="pt-2 text-right text-gray-500">Total costs</td>
                <td className="pt-2 text-right font-semibold">{money(totalCosts)}</td>
                {!isClosed && <td />}
              </tr>
            </tfoot>
          )}
        </table>
      </div>

      {editingId !== null && (
        <div className="border rounded p-3 space-y-2 bg-gray-50">
          {err && <div className="text-xs text-red-600">{err}</div>}
          <div className="grid grid-cols-2 gap-2">
            <div>
              <label className="block text-xs text-gray-600 mb-1">Label</label>
              <input className="w-full border rounded px-2 py-1.5 text-sm" value={label} onChange={e => setLabel(e.target.value)} placeholder="e.g. Venue hire" />
            </div>
            <div>
              <label className="block text-xs text-gray-600 mb-1">Type</label>
              <select className="w-full border rounded px-2 py-1.5 text-sm" value={costType} onChange={e => setCostType(e.target.value as EventCostType)}>
                <option value="once_off">Once-off / overall</option>
                <option value="per_item">Per item (ticket type)</option>
              </select>
            </div>
            {costType === "per_item" && (
              <div>
                <label className="block text-xs text-gray-600 mb-1">Ticket type</label>
                <select className="w-full border rounded px-2 py-1.5 text-sm" value={eventOptionId} onChange={e => setEventOptionId(e.target.value)}>
                  <option value="">Select…</option>
                  {eventOptions.map(o => <option key={o.id} value={o.id}>{o.name}</option>)}
                </select>
              </div>
            )}
            <div>
              <label className="block text-xs text-gray-600 mb-1">Amount {costType === "per_item" ? "(per ticket)" : "(flat total)"}</label>
              <input type="number" step="0.01" className="w-full border rounded px-2 py-1.5 text-sm" value={amount} onChange={e => setAmount(e.target.value)} />
            </div>
            <div>
              <label className="block text-xs text-gray-600 mb-1">Paid from (optional)</label>
              <select className="w-full border rounded px-2 py-1.5 text-sm" value={paidFromMethod} onChange={e => setPaidFromMethod(e.target.value as any)}>
                <option value="">Not from event takings</option>
                {METHODS.map(m => <option key={m} value={m}>{METHOD_LABELS[m]}</option>)}
              </select>
              <p className="text-[10px] text-gray-400 mt-0.5">If this was paid out of the door takings (e.g. cash to a vendor), tag it so the Cashup report deducts it from that method's expected amount.</p>
            </div>
            <div className="col-span-2">
              <label className="block text-xs text-gray-600 mb-1">Notes (optional)</label>
              <input className="w-full border rounded px-2 py-1.5 text-sm" value={notes} onChange={e => setNotes(e.target.value)} />
            </div>
          </div>
          <div className="flex gap-2 justify-end">
            <button className="text-xs px-3 py-1.5 rounded border" onClick={cancel} disabled={saving}>Cancel</button>
            <button className="text-xs px-3 py-1.5 rounded bg-brand-600 text-white hover:bg-brand-700" onClick={save} disabled={saving}>{saving ? "Saving…" : "Save"}</button>
          </div>
        </div>
      )}
    </div>
  );
}

// ─── Reconciliation tab ─────────────────────────────────────────────────────

type PersonDenom = { value: number; count: number };
type MethodTotals = { total: number; count: number };
type CashMethodTotals = MethodTotals & {
  actual: number | null; variance: number | null; denominations: PersonDenom[];
  enteredBy: { id: string; name: string } | null; countUpdatedAt: string | null; notes: string | null;
};
type AccountabilityRow = {
  userId: string | null; name: string; email: string | null;
  cash: CashMethodTotals; card: MethodTotals; eft: MethodTotals; other: MethodTotals;
};
type AccountabilityResponse = { rows: AccountabilityRow[]; cashActualTotal: number | null; cashDenominations: PersonDenom[] };

// Payment accountability, per staff member who recorded the payment, broken down by method —
// separate from the overall cash reconciliation above, which only totals the float without
// saying who's responsible for it. For cash, staff can optionally enter what was physically
// counted for each person, any time (not required to close the event); the event's cash actual
// is the live sum of these per-person counts, shown here and used by the reconciliation table.
function CashByUserSection({ eventId, token, onCashSummaryChange }: {
  eventId: string; token: string;
  onCashSummaryChange?: (summary: { actualTotal: number | null; denominations: PersonDenom[] }) => void;
}) {
  const [data, setData] = useState<AccountabilityResponse | null>(null);
  const [loading, setLoading] = useState(false);
  const [open, setOpen] = useState(true);
  const [editingUserId, setEditingUserId] = useState<string | null>(null);

  const load = () => {
    if (!token || !eventId) return;
    setLoading(true);
    apiFetch<AccountabilityResponse>(`/api/cashups/event/${eventId}/cash-by-user`, { authToken: token })
      .then(r => { setData(r); onCashSummaryChange?.({ actualTotal: r?.cashActualTotal ?? null, denominations: r?.cashDenominations || [] }); })
      .catch(() => setData({ rows: [], cashActualTotal: null, cashDenominations: [] }))
      .finally(() => setLoading(false));
  };

  useEffect(load, [eventId, token]);

  const rows = data?.rows || [];
  const sumOf = (m: "cash" | "card" | "eft" | "other", key: "total" | "count") =>
    rows.reduce((s, r) => s + (r[m][key] || 0), 0);
  const totalCash = sumOf("cash", "total");
  const totalCashActual = rows.reduce((s, r) => s + (r.cash.actual || 0), 0);
  const grandTotal = rows.reduce((s, r) => s + r.cash.total + r.card.total + r.eft.total + r.other.total, 0);

  return (
    <div className="bg-white border rounded-lg p-4 space-y-2">
      <button className="text-sm font-medium flex items-center gap-1" onClick={() => setOpen(o => !o)}>
        <span>{open ? "▾" : "▸"}</span> Payment accountability by staff member
      </button>
      {open && (
        loading ? (
          <div className="text-sm text-gray-400">Loading…</div>
        ) : rows.length === 0 ? (
          <div className="text-sm text-gray-500">No payments recorded for this event.</div>
        ) : (
          <div className="overflow-auto">
            <table className="w-full text-sm min-w-[760px] border-separate border-spacing-0">
              <thead>
                <tr className="text-gray-400 text-[10px] uppercase tracking-wide">
                  <th rowSpan={2} className="text-left align-bottom pb-1 pr-3">Staff member</th>
                  <th colSpan={3} className="text-center pb-1 border-l border-gray-100 px-2">Cash</th>
                  <th rowSpan={2} className="text-right align-bottom pb-1 border-l border-gray-100 px-2">Card</th>
                  <th rowSpan={2} className="text-right align-bottom pb-1 px-2">EFT</th>
                  <th rowSpan={2} className="text-right align-bottom pb-1 px-2">Other</th>
                  <th rowSpan={2} className="text-right align-bottom pb-1 border-l border-gray-100 px-2">Total</th>
                  <th rowSpan={2}></th>
                </tr>
                <tr className="text-left text-gray-500 border-b text-xs">
                  <th className="text-right pb-1.5 border-l border-gray-100 px-2 font-normal">Expected</th>
                  <th className="text-right pb-1.5 px-2 font-normal">Actual</th>
                  <th className="text-right pb-1.5 px-2 font-normal">Variance</th>
                  <th className="border-l border-gray-100"></th>
                  <th></th>
                  <th></th>
                  <th className="border-l border-gray-100"></th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                {rows.map(r => (
                  <React.Fragment key={r.userId || "unknown"}>
                    <tr className="border-b border-gray-100 last:border-0">
                      <td className="py-2.5 pr-3">
                        <div className="font-medium text-gray-800">{r.name}</div>
                        {r.email && <div className="text-xs text-gray-400">{r.email}</div>}
                      </td>
                      <td className="py-2.5 text-right border-l border-gray-100 px-2">{money(r.cash.total)}</td>
                      <td className="py-2.5 text-right px-2">{r.cash.actual != null ? money(r.cash.actual) : <span className="text-gray-300">—</span>}</td>
                      <td className="py-2.5 text-right px-2">
                        {r.cash.variance != null ? (
                          Math.abs(r.cash.variance) > 0.01 ? (
                            <span className={"inline-block px-1.5 py-0.5 rounded text-xs font-medium " + (r.cash.variance < 0 ? "bg-rose-50 text-rose-700" : "bg-amber-50 text-amber-700")}>
                              {money(r.cash.variance)}
                            </span>
                          ) : <span className="inline-block px-1.5 py-0.5 rounded text-xs font-medium bg-emerald-50 text-emerald-700">Matches</span>
                        ) : <span className="text-gray-300">—</span>}
                      </td>
                      <td className="py-2.5 text-right text-gray-600 border-l border-gray-100 px-2">{r.card.total > 0 ? money(r.card.total) : <span className="text-gray-300">—</span>}</td>
                      <td className="py-2.5 text-right text-gray-600 px-2">{r.eft.total > 0 ? money(r.eft.total) : <span className="text-gray-300">—</span>}</td>
                      <td className="py-2.5 text-right text-gray-600 px-2">{r.other.total > 0 ? money(r.other.total) : <span className="text-gray-300">—</span>}</td>
                      <td className="py-2.5 text-right font-medium border-l border-gray-100 px-2">{money(r.cash.total + r.card.total + r.eft.total + r.other.total)}</td>
                      <td className="py-2.5 text-right pl-2">
                        {r.userId && (
                          <button
                            className="text-xs text-brand-600 hover:underline whitespace-nowrap"
                            onClick={() => setEditingUserId(editingUserId === r.userId ? null : r.userId)}
                          >
                            {r.cash.actual != null ? "Edit count" : "Enter count"}
                          </button>
                        )}
                      </td>
                    </tr>
                    {r.userId && editingUserId === r.userId && (
                      <tr>
                        <td colSpan={9} className="pb-3">
                          <PersonCashCountEditor
                            eventId={eventId}
                            token={token}
                            userId={r.userId}
                            initialDenominations={r.cash.denominations}
                            initialNotes={r.cash.notes}
                            enteredBy={r.cash.enteredBy}
                            countUpdatedAt={r.cash.countUpdatedAt}
                            onSaved={() => { setEditingUserId(null); load(); }}
                            onCancel={() => setEditingUserId(null)}
                          />
                        </td>
                      </tr>
                    )}
                  </React.Fragment>
                ))}
                <tr className="font-semibold border-t border-gray-200">
                  <td className="py-2.5 pr-3">Total</td>
                  <td className="py-2.5 text-right border-l border-gray-100 px-2">{money(totalCash)}</td>
                  <td className="py-2.5 text-right px-2">{money(totalCashActual)}</td>
                  <td className="py-2.5 text-right px-2">{money(totalCashActual - totalCash)}</td>
                  <td className="py-2.5 text-right border-l border-gray-100 px-2">{money(sumOf("card", "total"))}</td>
                  <td className="py-2.5 text-right px-2">{money(sumOf("eft", "total"))}</td>
                  <td className="py-2.5 text-right px-2">{money(sumOf("other", "total"))}</td>
                  <td className="py-2.5 text-right border-l border-gray-100 px-2">{money(grandTotal)}</td>
                  <td></td>
                </tr>
              </tbody>
            </table>
          </div>
        )
      )}
    </div>
  );
}

// Denomination entry for one person's actual cash count — pick a denomination from the dropdown,
// enter how many, add it to the list. Repeatable, editable, removable before saving.
function PersonCashCountEditor({ eventId, token, userId, initialDenominations, initialNotes, enteredBy, countUpdatedAt, onSaved, onCancel }: {
  eventId: string; token: string; userId: string;
  initialDenominations: PersonDenom[]; initialNotes: string | null;
  enteredBy: { id: string; name: string } | null; countUpdatedAt: string | null;
  onSaved: () => void; onCancel: () => void;
}) {
  const initialCounts: Record<number, string> = {};
  for (const d of initialDenominations) initialCounts[d.value] = String(d.count);
  const [counts, setCounts] = useState<Record<number, string>>(initialCounts);
  const [notes, setNotes] = useState(initialNotes || "");
  const [saving, setSaving] = useState(false);
  const [err, setErr] = useState<string | null>(null);

  const setCount = (value: number, v: string) => setCounts(prev => ({ ...prev, [value]: v }));

  const lines: PersonDenom[] = ZAR_DENOMINATIONS
    .map(value => ({ value, count: parseInt(counts[value] || "0", 10) || 0 }))
    .filter(d => d.count > 0);

  const runningTotal = lines.reduce((s, l) => s + l.value * l.count, 0);

  const save = async () => {
    setSaving(true); setErr(null);
    try {
      await apiFetch(`/api/cashups/event/${eventId}/person-cash/${userId}`, {
        method: "PUT", authToken: token, body: { denominations: lines, notes: notes || null }
      });
      onSaved();
    } catch (e: any) {
      setErr(e?.message || "Failed to save count");
    } finally {
      setSaving(false);
    }
  };

  return (
    <div className="border rounded-lg p-3 bg-gray-50 space-y-3">
      {err && <div className="text-xs text-red-600">{err}</div>}
      {enteredBy && countUpdatedAt && (
        <div className="text-[11px] text-gray-500">Last entered by {enteredBy.name} on {new Date(countUpdatedAt).toLocaleString()}</div>
      )}

      <div className="grid grid-cols-2 sm:grid-cols-4 gap-2">
        {ZAR_DENOMINATIONS.map(v => (
          <div key={v} className="flex items-center gap-2">
            <span className="text-sm w-14">{denomLabel(v)}</span>
            <span className="text-xs text-gray-400">×</span>
            <input
              type="number"
              min={0}
              step={1}
              className="w-16 border rounded px-2 py-1 text-sm"
              value={counts[v] || ""}
              onChange={e => setCount(v, e.target.value)}
            />
          </div>
        ))}
      </div>

      <div className="text-sm font-medium">Total: {money(runningTotal)}</div>

      <div>
        <label className="block text-[11px] text-gray-600 mb-1">Notes (optional)</label>
        <input className="w-full border rounded px-2 py-1.5 text-sm" value={notes} onChange={e => setNotes(e.target.value)} />
      </div>

      <div className="flex gap-2 justify-end">
        <button className="text-xs px-3 py-1.5 rounded border" onClick={onCancel} disabled={saving}>Cancel</button>
        <button className="text-xs px-3 py-1.5 rounded bg-brand-600 text-white hover:bg-brand-700" onClick={save} disabled={saving}>{saving ? "Saving…" : "Save count"}</button>
      </div>
    </div>
  );
}

// ─── Report tab ──────────────────────────────────────────────────────────
// A clean, read-only summary of the cashup — opened automatically once the event is closed, so
// staff land straight on "here's what happened" instead of the editable Reconciliation tab.
function ReportTab({ eventId, token, data, isClosed }: {
  eventId: string; token: string; data: EventFinancials; isClosed: boolean;
}) {
  const reconciled = data.reconciled;
  const latestClose = data.history.find(h => h.action === "closed" || h.action === "quick_closed");

  return (
    <div className="space-y-4">
      <div className="bg-white border rounded-lg p-4">
        <div className="flex items-center justify-between mb-1">
          <div className="text-sm font-medium">Cashup report</div>
          <span className={"text-xs px-2 py-1 rounded " + (isClosed ? "bg-rose-50 text-rose-700" : "bg-emerald-50 text-emerald-700")}>
            {isClosed ? "Closed" : "Open (live preview)"}
          </span>
        </div>
        {latestClose ? (
          <div className="text-xs text-gray-500">
            {latestClose.action === "closed" ? "Closed (full cashup)" : "Quick closed"} by {latestClose.performedBy?.name || "Unknown"} on {new Date(latestClose.createdAt).toLocaleString()}
          </div>
        ) : (
          <div className="text-xs text-gray-500">This event hasn&apos;t been closed yet — figures below are a live preview and will change as more payments come in.</div>
        )}
      </div>

      <div className="bg-white border rounded-lg p-4 space-y-2 overflow-auto">
        <div className="text-sm font-medium">Revenue by method</div>
        <table className="w-full text-sm min-w-[560px]">
          <thead>
            <tr className="text-left text-gray-500 border-b">
              <th className="py-1">Method</th>
              <th className="py-1 text-right">Income</th>
              <th className="py-1 text-right">Expected cash</th>
              <th className="py-1 text-right">Actual</th>
              <th className="py-1 text-right">Variance</th>
            </tr>
          </thead>
          <tbody>
            {METHODS.map(m => {
              const r = reconciled?.byMethod?.[m];
              return (
                <tr key={m} className="border-b last:border-0">
                  <td className="py-1.5">{METHOD_LABELS[m]}</td>
                  <td className="py-1.5 text-right">{money(data.paymentsByMethod[m])}</td>
                  <td className="py-1.5 text-right">{money(data.expectedCashByMethod[m])}</td>
                  <td className="py-1.5 text-right">{r?.actual != null ? money(r.actual) : "—"}</td>
                  <td className="py-1.5 text-right">{r?.variance != null ? money(r.variance) : "—"}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>

      {reconciled?.byMethod?.cash?.denominations?.length ? (
        <div className="bg-white border rounded-lg p-4 space-y-2">
          <div className="text-sm font-medium">Cash denomination count</div>
          <table className="text-sm">
            <tbody>
              {reconciled.byMethod.cash.denominations.map((d: any) => (
                <tr key={d.id}><td className="pr-4 py-0.5">{denomLabel(d.value)}</td><td className="pr-4 py-0.5">× {d.count}</td><td className="py-0.5 text-gray-500">{money(d.value * d.count)}</td></tr>
              ))}
            </tbody>
          </table>
        </div>
      ) : null}

      <CashByUserSection eventId={eventId} token={token} />

      {data.costs.length > 0 && (
        <div className="bg-white border rounded-lg p-4 space-y-2 overflow-auto">
          <div className="text-sm font-medium">Costs</div>
          <table className="w-full text-sm min-w-[480px]">
            <thead>
              <tr className="text-left text-gray-500 border-b">
                <th className="py-1">Label</th>
                <th className="py-1">Paid from</th>
                <th className="py-1 text-right">Total</th>
              </tr>
            </thead>
            <tbody>
              {data.costs.map((c: any) => (
                <tr key={c.id} className="border-b last:border-0">
                  <td className="py-1.5">{c.label}</td>
                  <td className="py-1.5 capitalize">{c.paidFromMethod || "—"}</td>
                  <td className="py-1.5 text-right">{money(c.total ?? c.amount)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      <div className="bg-white border rounded-lg p-4 grid grid-cols-1 sm:grid-cols-3 gap-3 text-sm">
        <div>
          <div className="text-gray-500 text-xs">Donations counted as profit</div>
          <div className="font-semibold">{money(data.unallocatedDonationsTotal)}</div>
        </div>
        <div>
          <div className="text-gray-500 text-xs">Total costs</div>
          <div className="font-semibold">{money(data.totalCosts)}</div>
        </div>
        <div>
          <div className="text-gray-500 text-xs">Net profit</div>
          <div className="font-semibold">{money(data.netProfit)}</div>
        </div>
      </div>
    </div>
  );
}

function ReconciliationTab({ eventId, token, data, busy, setBusy, setError, onChanged, onClosed }: {
  eventId: string; token: string; data: EventFinancials; busy: boolean;
  setBusy: (b: boolean) => void; setError: (e: string | null) => void; onChanged: () => void; onClosed: () => void;
}) {
  const isClosed = data.event.cashupStatus === "closed";
  const draftLines = (data.event as any).cashupDraft?.lines as Array<{ method: string; actualAmount?: string | number; notes?: string; denominations?: { value: number; count: number }[] }> | undefined;

  const initialLines: Record<CashupMethod, LineInput> = useMemo(() => {
    const base: Record<CashupMethod, LineInput> = { cash: { actualAmount: "", notes: "" }, card: { actualAmount: "", notes: "" }, eft: { actualAmount: "", notes: "" }, other: { actualAmount: "", notes: "" } };
    for (const l of draftLines || []) {
      if (l.method in base) base[l.method as CashupMethod] = { actualAmount: l.actualAmount != null ? String(l.actualAmount) : "", notes: l.notes || "" };
    }
    return base;
  }, [draftLines]);

  const [lines, setLines] = useState<Record<CashupMethod, LineInput>>(initialLines);
  const [closeNotes, setCloseNotes] = useState("");
  const [reopenNotes, setReopenNotes] = useState("");
  // Cash no longer has its own manual entry — it's the live sum of every staff member's
  // per-person count, reported up from CashByUserSection below.
  const [cashSummary, setCashSummary] = useState<{ actualTotal: number | null; denominations: PersonDenom[] }>({ actualTotal: null, denominations: [] });

  useEffect(() => { setLines(initialLines); }, [initialLines]);

  const setLine = (method: CashupMethod, field: keyof LineInput, value: string) => {
    setLines(prev => ({ ...prev, [method]: { ...prev[method], [field]: value } }));
  };

  // Cash is included with notes only — its actual/denominations are always sourced server-side
  // from per-person counts (see cashupController.closeEvent), never from this payload.
  const buildLinesPayload = () => METHODS.map(m => m === "cash"
    ? { method: "cash", notes: lines.cash.notes || null }
    : { method: m, actualAmount: lines[m].actualAmount === "" ? null : parseFloat(lines[m].actualAmount), notes: lines[m].notes || null });

  const saveDraft = async () => {
    setBusy(true); setError(null);
    try {
      await apiFetch(`/api/cashups/event/${eventId}/draft`, { method: "PUT", authToken: token, body: { lines: buildLinesPayload() } });
      onChanged();
    } catch (e: any) {
      setError(e?.message || "Failed to save draft");
    } finally {
      setBusy(false);
    }
  };

  const closeWithCashup = async () => {
    if (!confirm("Close this event with the entered reconciliation? This will count unallocated donations as profit and fully lock the event until it's reopened.")) return;
    setBusy(true); setError(null);
    try {
      await apiFetch(`/api/cashups/event/${eventId}/close`, { method: "POST", authToken: token, body: { lines: buildLinesPayload(), notes: closeNotes || null } });
      onChanged();
      onClosed();
    } catch (e: any) {
      setError(e?.message || "Failed to close event");
    } finally {
      setBusy(false);
    }
  };

  const quickClose = async () => {
    if (!confirm("Quick close this event without a per-method cashup? System totals will be accepted as-is, unallocated donations will be counted as profit, and the event will be fully locked until it's reopened.")) return;
    setBusy(true); setError(null);
    try {
      await apiFetch(`/api/cashups/event/${eventId}/close`, { method: "POST", authToken: token, body: { notes: closeNotes || null } });
      onChanged();
      onClosed();
    } catch (e: any) {
      setError(e?.message || "Failed to close event");
    } finally {
      setBusy(false);
    }
  };

  const reopen = async () => {
    if (!confirm("Reopen this event? Registrations, payments, refunds and donations will be allowed again.")) return;
    setBusy(true); setError(null);
    try {
      await apiFetch(`/api/cashups/event/${eventId}/reopen`, { method: "POST", authToken: token, body: { notes: reopenNotes || null } });
      onChanged();
    } catch (e: any) {
      setError(e?.message || "Failed to reopen event");
    } finally {
      setBusy(false);
    }
  };

  const reconciled = data.reconciled;

  return (
    <div className="space-y-4">
      <div className="bg-white border rounded-lg p-4 space-y-3 overflow-auto">
        <div className="text-sm font-medium">Cash-up reconciliation</div>
        <table className="w-full text-sm min-w-[640px]">
          <thead>
            <tr className="text-left text-gray-500 border-b">
              <th className="py-1">Method</th>
              <th className="py-1 text-right">Income</th>
              <th className="py-1 text-right">Costs from method</th>
              <th className="py-1 text-right">Expected cash</th>
              <th className="py-1 text-right">Actual</th>
              <th className="py-1 text-right">Variance</th>
              <th className="py-1">Notes</th>
            </tr>
          </thead>
          <tbody>
            {METHODS.map(m => {
              const r = reconciled?.byMethod?.[m];
              return (
                <tr key={m} className="border-b last:border-0 align-top">
                  <td className="py-1.5">{METHOD_LABELS[m]}</td>
                  <td className="py-1.5 text-right">{money(data.paymentsByMethod[m])}</td>
                  <td className="py-1.5 text-right">{money(data.costsByMethod[m])}</td>
                  <td className="py-1.5 text-right">{money(data.expectedCashByMethod[m])}</td>
                  <td className="py-1.5 text-right">
                    {isClosed ? (
                      money(r?.actual ?? null)
                    ) : m === "cash" ? (
                      cashSummary.actualTotal != null ? money(cashSummary.actualTotal) : <span className="text-gray-400">not counted</span>
                    ) : (
                      <input type="number" step="0.01" className="w-28 border rounded px-2 py-1 text-sm text-right" value={lines[m].actualAmount} onChange={e => setLine(m, "actualAmount", e.target.value)} />
                    )}
                  </td>
                  <td className="py-1.5 text-right">
                    {isClosed
                      ? (r?.variance != null ? money(r.variance) : <span className="text-gray-400">not reconciled</span>)
                      : (m === "cash"
                        ? (cashSummary.actualTotal != null ? money(cashSummary.actualTotal - data.expectedCashByMethod[m]) : "—")
                        : (lines[m].actualAmount !== "" ? money(parseFloat(lines[m].actualAmount) - data.expectedCashByMethod[m]) : "—"))}
                  </td>
                  <td className="py-1.5">
                    {isClosed ? (r?.notes || "—") : (
                      <input className="w-full border rounded px-2 py-1 text-sm" value={lines[m].notes} onChange={e => setLine(m, "notes", e.target.value)} />
                    )}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
        {!isClosed && (
          <div className="text-xs text-gray-500">Cash actual is the live sum of per-staff-member counts entered below — there's no separate event-wide entry.</div>
        )}
      </div>

      <CashByUserSection eventId={eventId} token={token} onCashSummaryChange={setCashSummary} />

      <div className="bg-white border rounded-lg p-4 space-y-2">
        <div className="text-sm font-medium">Cash denomination count</div>
        {(() => {
          const denoms = isClosed ? (reconciled?.byMethod?.cash?.denominations || []) : cashSummary.denominations;
          return denoms.length > 0 ? (
            <table className="text-sm">
              <tbody>
                {denoms.map((d: any) => (
                  <tr key={d.id || d.value}><td className="pr-4 py-0.5">{denomLabel(d.value)}</td><td className="pr-4 py-0.5">× {d.count}</td><td className="py-0.5 text-gray-500">{money(d.value * d.count)}</td></tr>
                ))}
              </tbody>
            </table>
          ) : (
            <div className="text-xs text-gray-400">
              {isClosed ? "No denomination breakdown recorded for this cashup." : "No per-staff-member cash counts entered yet — see “Payment accountability by staff member” above."}
            </div>
          );
        })()}
      </div>

      <div className="bg-white border rounded-lg p-4 grid grid-cols-1 sm:grid-cols-3 gap-3 text-sm">
        <div>
          <div className="text-gray-500 text-xs">Donations counted as profit</div>
          <div className="font-semibold">{money(data.unallocatedDonationsTotal)}</div>
        </div>
        <div>
          <div className="text-gray-500 text-xs">Total costs</div>
          <div className="font-semibold">{money(data.totalCosts)}</div>
        </div>
        <div>
          <div className="text-gray-500 text-xs">Net profit</div>
          <div className="font-semibold">{money(data.netProfit)}</div>
        </div>
      </div>

      {!isClosed && (
        <div className="bg-white border rounded-lg p-4 space-y-2">
          <label className="block text-xs text-gray-600 mb-1">Notes for closing (optional)</label>
          <input className="w-full border rounded px-2 py-1.5 text-sm" value={closeNotes} onChange={e => setCloseNotes(e.target.value)} />
          <div className="flex flex-wrap gap-2 justify-end pt-1">
            <button className="text-xs px-3 py-1.5 rounded border" disabled={busy} onClick={saveDraft}>Save draft</button>
            <button className="text-xs px-3 py-1.5 rounded bg-amber-600 text-white hover:bg-amber-700" disabled={busy} onClick={quickClose}>Quick close (skip cashup)</button>
            <button className="text-xs px-3 py-1.5 rounded bg-brand-600 text-white hover:bg-brand-700" disabled={busy} onClick={closeWithCashup}>Close event with cashup</button>
          </div>
        </div>
      )}

      {isClosed && (
        <div className="bg-white border rounded-lg p-4 space-y-2">
          <label className="block text-xs text-gray-600 mb-1">Notes for reopening (optional)</label>
          <input className="w-full border rounded px-2 py-1.5 text-sm" value={reopenNotes} onChange={e => setReopenNotes(e.target.value)} />
          <div className="flex justify-end">
            <button className="text-xs px-3 py-1.5 rounded bg-rose-600 text-white hover:bg-rose-700" disabled={busy} onClick={reopen}>Reopen event</button>
          </div>
        </div>
      )}

      <div className="bg-white border rounded-lg p-4 space-y-2">
        <div className="text-sm font-medium">History</div>
        {data.history.length === 0 && <div className="text-xs text-gray-400">No close/reopen actions yet.</div>}
        <ul className="space-y-1.5">
          {data.history.map(h => (
            <li key={h.id} className="text-xs border-b last:border-0 pb-1.5 flex items-center justify-between gap-3">
              <span>
                <span className="font-medium">{h.action === "closed" ? "Closed (full cashup)" : h.action === "quick_closed" ? "Quick closed" : "Reopened"}</span>
                {" — "}{h.performedBy?.name || "Unknown"} — {new Date(h.createdAt).toLocaleString()}
              </span>
              {(h.action === "closed" || h.action === "quick_closed") && (
                <span className="text-gray-500 shrink-0">Donations to profit {money(h.unallocatedDonationsTotal)} · Costs {money(h.totalCosts)}</span>
              )}
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
}
