"use client";

import { useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import { buttonClass } from "@/components/ui";

export interface BuyerTicket {
  id: string;
  code: string;
  typeName: string;
  status: "valid" | "used" | "void";
  admitsCount: number;
}

export interface BuyerOrder {
  id: string;
  name: string | null;
  email: string;
  phone: string | null;
  createdAt: string;
  method: string;
  total: string;
  status: "paid" | "pending";
  tickets: BuyerTicket[];
}

// Kenyan numbers for wa.me: 07.. / 01.. -> 2547.. / 2541..
function waNumber(phone: string) {
  const d = phone.replace(/\D/g, "");
  if (d.startsWith("254")) return d;
  if (d.startsWith("0")) return "254" + d.slice(1);
  if (d.length === 9) return "254" + d;
  return d;
}

const dateFmt = new Intl.DateTimeFormat("en-KE", {
  day: "numeric",
  month: "short",
  hour: "2-digit",
  minute: "2-digit",
  timeZone: "Africa/Nairobi",
});

export default function BuyersTable({
  paid,
  pending,
  canEdit,
}: {
  paid: BuyerOrder[];
  pending: BuyerOrder[];
  canEdit: boolean;
}) {
  const [tab, setTab] = useState<"paid" | "pending">("paid");
  const [q, setQ] = useState("");
  const [openId, setOpenId] = useState<string | null>(null);

  const rows = tab === "paid" ? paid : pending;
  const filtered = useMemo(() => {
    const term = q.trim().toLowerCase();
    if (!term) return rows;
    const digits = term.replace(/\D/g, "").slice(-9);
    return rows.filter(
      (o) =>
        (o.name ?? "").toLowerCase().includes(term) ||
        o.email.toLowerCase().includes(term) ||
        (digits.length >= 4 && (o.phone ?? "").replace(/\D/g, "").includes(digits)) ||
        o.tickets.some((t) => t.code.includes(term))
    );
  }, [rows, q]);

  return (
    <div className="space-y-3">
      <div className="flex flex-wrap items-center gap-2">
        <button
          type="button"
          onClick={() => setTab("paid")}
          className={`be-act ${tab === "paid" ? "be-act-primary" : "be-act-ghost"}`}
        >
          Buyers ({paid.length})
        </button>
        <button
          type="button"
          onClick={() => setTab("pending")}
          className={`be-act ${tab === "pending" ? "be-act-primary" : "be-act-ghost"}`}
          title="People who started checkout in the last 7 days but haven't paid (yet)"
        >
          Incoming / unpaid ({pending.length})
        </button>
        <input
          value={q}
          onChange={(e) => setQ(e.target.value)}
          placeholder="Search name, email, phone or ticket code"
          className="input ml-auto w-full sm:w-72 text-sm"
        />
      </div>

      {tab === "pending" && (
        <p className="text-xs text-be-muted">
          Checkouts started in the last 7 days that haven&apos;t been paid. Most complete within a minute;
          the rest are worth a follow-up call.
        </p>
      )}

      <div className="overflow-x-auto rounded-lg border border-be-border">
        <table className="w-full text-sm">
          <thead className="bg-be-surface text-left text-xs text-be-muted">
            <tr>
              <th className="p-3 font-medium">Buyer</th>
              <th className="p-3 font-medium">Phone</th>
              <th className="p-3 font-medium">Email</th>
              <th className="p-3 font-medium">Tickets</th>
              <th className="p-3 font-medium text-right">Amount</th>
              <th className="p-3 font-medium">When</th>
              {tab === "paid" && <th className="p-3" />}
            </tr>
          </thead>
          <tbody>
            {filtered.map((o) => {
              const active = o.tickets.filter((t) => t.status !== "void");
              const summary = summarize(active);
              return (
                <OrderRow
                  key={o.id}
                  order={o}
                  summary={summary || (o.status === "pending" ? "—" : "All cancelled")}
                  expanded={openId === o.id}
                  onToggle={() => setOpenId(openId === o.id ? null : o.id)}
                  showActions={tab === "paid"}
                  canEdit={canEdit}
                />
              );
            })}
            {filtered.length === 0 && (
              <tr>
                <td colSpan={7} className="p-4 text-be-muted">
                  {q ? "No buyers match that search." : tab === "paid" ? "No paid orders yet." : "No unpaid checkouts."}
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function summarize(ts: BuyerTicket[]) {
  const counts = new Map<string, number>();
  for (const t of ts) counts.set(t.typeName, (counts.get(t.typeName) ?? 0) + 1);
  return [...counts].map(([n, c]) => `${c}× ${n}`).join(", ");
}

function OrderRow({
  order: o,
  summary,
  expanded,
  onToggle,
  showActions,
  canEdit,
}: {
  order: BuyerOrder;
  summary: string;
  expanded: boolean;
  onToggle: () => void;
  showActions: boolean;
  canEdit: boolean;
}) {
  return (
    <>
      <tr className="border-t border-be-border align-top">
        <td className="p-3 font-medium text-be-text">{o.name || "—"}</td>
        <td className="p-3 whitespace-nowrap">
          {o.phone ? (
            <span className="flex items-center gap-2">
              <a href={`tel:${o.phone}`} className="text-be-text hover:underline">
                {o.phone}
              </a>
              <a
                href={`https://wa.me/${waNumber(o.phone)}`}
                target="_blank"
                rel="noreferrer"
                className="text-xs text-brand-green-h hover:underline"
              >
                WhatsApp
              </a>
            </span>
          ) : (
            <span className="text-be-muted">—</span>
          )}
        </td>
        <td className="p-3">
          <a href={`mailto:${o.email}`} className="break-all text-be-text hover:underline">
            {o.email}
          </a>
        </td>
        <td className="p-3 text-be-muted">{summary}</td>
        <td className="p-3 text-right whitespace-nowrap text-be-text">{o.total}</td>
        <td className="p-3 whitespace-nowrap text-be-muted">
          {dateFmt.format(new Date(o.createdAt))}
          <span className="block text-xs">{o.method}</span>
        </td>
        {showActions && (
          <td className="p-3 text-right">
            <button type="button" onClick={onToggle} className="be-act be-act-ghost whitespace-nowrap">
              {expanded ? "Close" : "Tickets / upgrade"}
            </button>
          </td>
        )}
      </tr>
      {expanded && (
        <tr className="border-t border-be-border bg-be-surface">
          <td colSpan={7} className="p-4">
            <UpgradePanel order={o} canEdit={canEdit} />
          </td>
        </tr>
      )}
    </>
  );
}

const STATUS_TEXT: Record<BuyerTicket["status"], string> = {
  valid: "Valid",
  used: "Checked in",
  void: "Cancelled",
};

// Cancel selected tickets so the buyer can upgrade (e.g. Regular -> VIP).
// Optionally issues a one-time credit code worth what they paid, which they
// enter at checkout on the event page to pay only the difference.
export function UpgradePanel({ order, canEdit }: { order: BuyerOrder; canEdit: boolean }) {
  const router = useRouter();
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [issueCredit, setIssueCredit] = useState(true);
  const [notify, setNotify] = useState(true);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [done, setDone] = useState<{ code: string | null; kes: number; email: string; sms: string } | null>(null);

  const toggle = (t: BuyerTicket) => {
    setSelected((prev) => {
      const next = new Set(prev);
      // Group tickets go together (one bundle = several QRs).
      const group =
        t.admitsCount > 1
          ? order.tickets.filter((x) => x.typeName === t.typeName && x.status === "valid").map((x) => x.id)
          : [t.id];
      const on = !next.has(t.id);
      for (const id of group) {
        if (on) next.add(id);
        else next.delete(id);
      }
      return next;
    });
  };

  async function submit() {
    if (!selected.size) return;
    const ok = window.confirm(
      `Cancel ${selected.size} ticket${selected.size === 1 ? "" : "s"} for ${order.name || order.email}? Their QR code will stop working at the gate.`
    );
    if (!ok) return;
    setBusy(true);
    setError(null);
    const res = await fetch(`/api/dashboard/orders/${order.id}/cancel-for-upgrade`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ ticketIds: [...selected], issueCredit, notify }),
    }).catch(() => null);
    const data = res ? await res.json().catch(() => ({})) : {};
    setBusy(false);
    if (!res || !res.ok) {
      setError(data.error || "Could not cancel the tickets");
      return;
    }
    setDone({ code: data.creditCode, kes: data.creditCents / 100, email: data.emailStatus, sms: data.smsStatus });
    setSelected(new Set());
    router.refresh();
  }

  return (
    <div className="space-y-3 text-sm">
      <ul className="space-y-1.5">
        {order.tickets.map((t) => (
          <li key={t.id} className="flex flex-wrap items-center gap-3">
            {canEdit && (
              <input
                type="checkbox"
                disabled={t.status !== "valid" || busy}
                checked={selected.has(t.id)}
                onChange={() => toggle(t)}
                aria-label={`Select ${t.typeName} ticket ${t.code}`}
              />
            )}
            <span className="font-medium text-be-text">{t.typeName}</span>
            <span className="font-mono text-xs text-be-muted">{t.code}</span>
            <span
              className={`rounded-full px-2 py-0.5 text-xs ${
                t.status === "valid" ? "pill-ok" : t.status === "used" ? "pill-info" : "pill-muted"
              }`}
            >
              {STATUS_TEXT[t.status]}
            </span>
          </li>
        ))}
      </ul>

      {canEdit && order.tickets.some((t) => t.status === "valid") && (
        <div className="space-y-2 rounded-lg border border-be-border p-3">
          <p className="font-medium text-be-text">Cancel for upgrade</p>
          <p className="text-xs text-be-muted">
            Tick the ticket(s) the buyer wants to swap (e.g. Regular), then cancel. The seat goes back on
            sale and the old QR stops scanning. With credit on, the buyer gets a one-time code worth what
            they paid — they buy the VIP/VVIP ticket on the event page with it and pay only the difference.
          </p>
          <label className="flex items-center gap-2">
            <input type="checkbox" checked={issueCredit} onChange={(e) => setIssueCredit(e.target.checked)} />
            Give the buyer upgrade credit for what they paid
          </label>
          <label className="flex items-center gap-2">
            <input type="checkbox" checked={notify} onChange={(e) => setNotify(e.target.checked)} />
            Email / SMS the buyer
          </label>
          <button
            type="button"
            onClick={submit}
            disabled={busy || selected.size === 0}
            className={buttonClass("danger")}
          >
            {busy ? "Cancelling…" : `Cancel ${selected.size || ""} selected ticket${selected.size === 1 ? "" : "s"}`}
          </button>
          {error && <p className="text-red-500">{error}</p>}
        </div>
      )}

      {done && (
        <div className="rounded-lg p-3 pill-ok">
          <p className="font-medium">Tickets cancelled.</p>
          {done.code ? (
            <p className="mt-1">
              Upgrade code: <span className="font-mono text-base font-bold">{done.code}</span> — worth KES{" "}
              {done.kes.toLocaleString("en-KE")}. The buyer enters it at checkout on the event page.
            </p>
          ) : (
            <p className="mt-1">No credit issued.</p>
          )}
          <p className="mt-1 text-xs opacity-80">
            Email: {done.email} · SMS: {done.sms}
          </p>
        </div>
      )}
    </div>
  );
}
