/* ============================================================
   ADMIN PORTAL — box office, payments, reservations, QR door
   ============================================================ */
function FauxQR({ value, size = 132 }) {
  const N = 21;
  let seed = 5381; for (let i = 0; i < value.length; i++) seed = ((seed * 33) ^ value.charCodeAt(i)) >>> 0;
  const rng = () => { seed = (seed * 1103515245 + 12345) >>> 0; return seed / 4294967296; };
  const finder = (r, c) => (r < 7 && c < 7) || (r < 7 && c >= N - 7) || (r >= N - 7 && c < 7);
  const cells = [];
  for (let r = 0; r < N; r++) for (let c = 0; c < N; c++) {
    let on;
    if (finder(r, c)) { const rr = r % (N - 7 === r - (r >= N - 7 ? N - 7 : 0) ? 1 : 7); const lr = r >= N - 7 ? r - (N - 7) : r; const lc = c >= N - 7 ? c - (N - 7) : c; on = (lr === 0 || lr === 6 || lc === 0 || lc === 6 || (lr >= 2 && lr <= 4 && lc >= 2 && lc <= 4)); }
    else on = rng() > 0.5;
    cells.push(on);
  }
  return (
    <div style={{ width: size, height: size, background: "#fff", padding: 6, borderRadius: 8, display: "grid", gridTemplateColumns: `repeat(${N},1fr)`, gridTemplateRows: `repeat(${N},1fr)` }}>
      {cells.map((on, i) => <div key={i} style={{ background: on ? "#0B0B0C" : "#fff" }}></div>)}
    </div>
  );
}

function ChargeButton({ amount, label, onDone, className = "" }) {
  const t = useT();
  const [st, setSt] = useState("idle");
  const run = () => { if (st !== "idle") return; setSt("proc"); setTimeout(() => { setSt("done"); onDone && onDone(); }, 1300); };
  return (
    <button onClick={run} disabled={st !== "idle"} className={"gbtn w-full py-3.5 rounded-full text-[12px] font-bold uppercase tracking-[0.14em] transition-all flex items-center justify-center gap-2 " + (st === "done" ? "bg-green-500/90 text-white" : "bg-coral hover:bg-coral-deep text-white") + " " + className}>
      {st === "idle" && <>{label || t("Charge", "Cobrar")} ${amount}</>}
      {st === "proc" && <><span className="w-4 h-4 border-2 border-white/40 border-t-white rounded-full animate-spin"></span>{t("Processing…", "Procesando…")}</>}
      {st === "done" && <><Icon name="check" className="w-4 h-4" />{t("Charged", "Cobrado")} ${amount}</>}
    </button>
  );
}

function CardOnFile() {
  const t = useT();
  return (
    <div className="flex items-center gap-3 rounded-xl border border-white/12 bg-ink p-3">
      <div className="w-9 h-6 rounded bg-gradient-to-br from-coral to-grape"></div>
      <div className="flex-1"><div className="text-sm font-semibold">•••• •••• •••• 4242</div><div className="text-white/40 text-[11px]">{t("Authorized card on file", "Tarjeta autorizada en archivo")}</div></div>
      <Icon name="shield-check" className="w-5 h-5 text-green-400" />
    </div>
  );
}

/* ---------- BOX OFFICE (POS) ---------- */
function BoxOffice() {
  const t = useT(); const { lang } = useLang();
  const { TICKET_TYPES, MERCH, TIERS, EXPERIENCES } = window.PP;
  const cats = [["tickets", t("Tickets", "Tickets")], ["merch", t("Merch", "Merch")], ["membership", t("Membership", "Membresía")], ["experience", t("Experiences", "Experiencias")]];
  const [cat, setCat] = useState("tickets");
  const items = cat === "tickets" ? TICKET_TYPES.map((x) => ({ name: L(x.name, lang), price: x.price }))
    : cat === "merch" ? MERCH.map((x) => ({ name: x.name, price: x.price }))
    : cat === "membership" ? TIERS.map((x) => ({ name: x.name + " / mo", price: x.price }))
    : EXPERIENCES.map((x) => ({ name: L(x.name, lang), price: x.from }));
  const [sel, setSel] = useState(0);
  const [qty, setQty] = useState(1);
  const [receipt, setReceipt] = useState(null);
  const item = items[sel] || items[0];
  const total = (item ? item.price : 0) * qty;
  const code = "PP-" + Math.random().toString(16).slice(2, 8).toUpperCase();

  if (receipt) return (
    <div className="fade-view max-w-md mx-auto text-center">
      <div className="rounded-3xl border border-white/12 bg-card p-7">
        <div className="w-14 h-14 rounded-full bg-green-500/15 border border-green-500 flex items-center justify-center mx-auto mb-4"><Icon name="check" className="w-7 h-7 text-green-400" /></div>
        <h3 className="text-2xl font-black uppercase mb-1">{t("Payment complete", "Pago completado")}</h3>
        <p className="text-white/55 text-sm mb-5">{receipt.qty}× {receipt.name} · <b className="text-gold-soft">${receipt.total}</b></p>
        {receipt.cat === "tickets" && <div className="flex flex-col items-center gap-3 mb-5"><FauxQR value={receipt.code} /><div className="font-mono text-coral tracking-widest text-sm">{receipt.code}</div><p className="text-white/45 text-xs">{t("Scannable ticket sent to guest's phone & email.", "Ticket escaneable enviado al teléfono y correo del cliente.")}</p></div>}
        <PrimaryBtn onClick={() => { setReceipt(null); setQty(1); }} icon="plus">{t("New sale", "Nueva venta")}</PrimaryBtn>
      </div>
    </div>
  );

  return (
    <div className="grid lg:grid-cols-12 gap-6">
      <div className="lg:col-span-7">
        <div className="flex gap-2 mb-5 overflow-x-auto">{cats.map(([id, lbl]) => <button key={id} onClick={() => { setCat(id); setSel(0); }} className={"shrink-0 px-4 py-2 rounded-full text-[11px] font-bold uppercase tracking-wider transition-all " + (cat === id ? "bg-coral text-white" : "bg-white/5 border border-white/10 text-white/60 hover:text-white")}>{lbl}</button>)}</div>
        <div className="grid sm:grid-cols-2 gap-2.5">
          {items.map((it, i) => (
            <button key={i} onClick={() => setSel(i)} className={"flex items-center justify-between gap-3 p-4 rounded-xl border text-left transition-all " + (sel === i ? "border-coral bg-coral/10" : "border-white/12 hover:border-white/30 bg-card")}>
              <span className="font-semibold text-sm">{it.name}</span><span className="serif text-lg text-gold-soft">${it.price}</span>
            </button>
          ))}
        </div>
      </div>
      <div className="lg:col-span-5">
        <div className="rounded-2xl border border-white/12 bg-card p-6 lg:sticky lg:top-28">
          <div className="label text-white/45 text-[10px] mb-1">{t("Selling", "Vendiendo")}</div>
          <div className="text-xl font-black uppercase mb-4">{item ? item.name : "—"}</div>
          {(cat === "tickets" || cat === "merch") && (
            <div className="flex items-center justify-between mb-4"><span className="text-sm text-white/60">{t("Quantity", "Cantidad")}</span>
              <div className="flex items-center gap-3"><button onClick={() => setQty((q) => Math.max(1, q - 1))} className="w-8 h-8 rounded-lg bg-white/5 flex items-center justify-center"><Icon name="minus" className="w-4 h-4" /></button><span className="font-bold w-6 text-center">{qty}</span><button onClick={() => setQty((q) => q + 1)} className="w-8 h-8 rounded-lg bg-white/5 flex items-center justify-center"><Icon name="plus" className="w-4 h-4" /></button></div>
            </div>
          )}
          <div className="flex items-center justify-between py-3 border-t border-b border-white/10 mb-4"><span className="font-bold uppercase tracking-wide text-sm">{t("Total", "Total")}</span><span className="serif text-3xl text-gold-soft">${total}</span></div>
          <div className="mb-4"><CardOnFile /></div>
          <ChargeButton amount={total} label={t("Charge", "Cobrar")} onDone={() => setReceipt({ name: item.name, qty, total, cat, code })} />
        </div>
      </div>
    </div>
  );
}

/* ---------- RESERVATIONS + CANCELLATION FEE ---------- */
function AdminReservations() {
  const t = useT(); const { lang } = useLang();
  const [rows, setRows] = useState([
    { code: "R-2207", name: "Sofía Restrepo", table: "VIP 1", party: 6, status: "confirmed", fee: 0 },
    { code: "R-2208", name: "Tyler Brooks", table: "22", party: 10, status: "confirmed", fee: 0 },
    { code: "R-2209", name: "Ana Gómez", table: "41", party: 4, status: "no-show", fee: 0 },
    { code: "R-2210", name: "Marcus Lee", table: "107", party: 6, status: "confirmed", fee: 0 },
  ]);
  const [feeFor, setFeeFor] = useState(null);
  const [amount, setAmount] = useState(100);

  return (
    <div>
      <div className="space-y-2.5">
        {rows.map((r, i) => (
          <div key={r.code} className="flex items-center gap-4 p-4 rounded-2xl border border-white/10 bg-card">
            <div className="w-12 h-12 rounded-xl bg-coral/12 border border-coral/30 flex items-center justify-center font-extrabold text-coral shrink-0 text-sm">{r.table}</div>
            <div className="flex-1 min-w-0"><div className="font-bold text-sm truncate">{r.name}</div><div className="text-white/45 text-xs">{r.code} · {r.party} {t("guests", "personas")}</div></div>
            <Chip color={r.status === "no-show" ? "#FF6B5B" : "#5FBFA8"}>{r.status === "no-show" ? t("No-show", "No-show") : t("Confirmed", "Confirmada")}</Chip>
            {r.fee > 0 ? <span className="text-green-400 text-xs font-bold flex items-center gap-1"><Icon name="check" className="w-3.5 h-3.5" />${r.fee}</span>
              : <button onClick={() => { setFeeFor(i); setAmount(r.status === "no-show" ? 150 : 100); }} className="px-4 py-2 rounded-full border border-white/20 text-white text-[11px] font-bold uppercase tracking-wider hover:bg-coral hover:border-coral transition-all">{t("Charge fee", "Cobrar tarifa")}</button>}
          </div>
        ))}
      </div>

      {feeFor !== null && (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-6 bg-black/70 backdrop-blur-sm fade-view" onClick={() => setFeeFor(null)}>
          <div className="w-full max-w-sm rounded-3xl border border-white/12 bg-ink p-6" onClick={(e) => e.stopPropagation()}>
            <div className="flex items-center justify-between mb-4"><h3 className="text-xl font-black uppercase">{t("Cancellation fee", "Tarifa de cancelación")}</h3><button onClick={() => setFeeFor(null)}><Icon name="x" className="w-5 h-5 text-white/50" /></button></div>
            <p className="text-white/55 text-sm mb-4">{rows[feeFor].name} · {t("Table", "Mesa")} {rows[feeFor].table}</p>
            <div className="flex items-center gap-2 mb-4">{[50, 100, 150, 250].map((a) => <button key={a} onClick={() => setAmount(a)} className={"flex-1 py-2.5 rounded-xl text-sm font-bold transition-all " + (amount === a ? "bg-coral text-white" : "bg-card border border-white/12 text-white/60")}>${a}</button>)}</div>
            <div className="mb-4"><CardOnFile /></div>
            <ChargeButton amount={amount} label={t("Charge fee", "Cobrar tarifa")} onDone={() => { setRows((rs) => rs.map((x, j) => j === feeFor ? { ...x, fee: amount } : x)); setTimeout(() => setFeeFor(null), 900); }} />
            <p className="text-white/40 text-[11px] text-center mt-3">{t("Charged to the guest's authorized card per cancellation policy.", "Se cobra a la tarjeta autorizada del cliente según la política de cancelación.")}</p>
          </div>
        </div>
      )}
    </div>
  );
}

/* ---------- DOOR / QR SCANNER — verifies real admin-issued invitations ---------- */
function DoorScanner() {
  const t = useT(); const { lang } = useLang();
  const guests = useInvites();
  const [flash, setFlash] = useState(null);
  const [manual, setManual] = useState("");
  const visible = guests.filter((g) => g.status !== "cancelled");
  const inside = visible.filter((g) => g.status === "in");
  const pending = visible.filter((g) => g.status === "active");
  const fmtAt = (iso) => iso ? new Date(iso).toLocaleTimeString(lang === "es" ? "es" : "en", { hour: "numeric", minute: "2-digit" }) : "";
  const checkIn = (inv) => {
    window.PPDB.invites.checkIn(inv.id);
    setFlash({ ok: true, name: inv.name, code: inv.code });
    setTimeout(() => setFlash(null), 1800);
  };
  const submitManual = (e) => {
    e.preventDefault();
    const inv = window.PPDB.invites.byCode(manual);
    if (!inv) setFlash({ ok: false, msg: t("Code not found", "Código no encontrado") });
    else if (inv.status === "in") setFlash({ ok: false, msg: t("Already checked in", "Ya entró") });
    else if (inv.status === "cancelled") setFlash({ ok: false, msg: t("Invitation cancelled", "Invitación cancelada") });
    else { checkIn(inv); setManual(""); return; }
    setManual(""); setTimeout(() => setFlash(null), 1800);
  };

  return (
    <div className="grid lg:grid-cols-12 gap-6">
      {/* scanner */}
      <div className="lg:col-span-5">
        <div className="rounded-2xl border border-white/12 bg-card p-5">
          <div className="relative aspect-square rounded-2xl overflow-hidden bg-black mb-4" style={{ backgroundImage: "radial-gradient(circle at 50% 50%, #1a1a1d, #000)" }}>
            {/* viewfinder */}
            <div className="absolute inset-8 border-2 border-coral/70 rounded-2xl"></div>
            <div className="absolute left-8 right-8 h-0.5 bg-coral shadow-[0_0_12px_var(--c-coral)]" style={{ animation: "scanline 2.2s ease-in-out infinite", top: "20%" }}></div>
            {[["top-6 left-6", "border-t-2 border-l-2"], ["top-6 right-6", "border-t-2 border-r-2"], ["bottom-6 left-6", "border-b-2 border-l-2"], ["bottom-6 right-6", "border-b-2 border-r-2"]].map(([pos, b], i) => <div key={i} className={"absolute w-6 h-6 border-white/80 " + pos + " " + b}></div>)}
            {flash && (
              <div className={"absolute inset-0 flex flex-col items-center justify-center text-center p-6 fade-view " + (flash.ok ? "bg-green-500/20" : "bg-coral/20") + " backdrop-blur-sm"}>
                <Icon name={flash.ok ? "check-circle" : "alert-circle"} className={"w-14 h-14 mb-2 " + (flash.ok ? "text-green-400" : "text-coral")} />
                {flash.ok ? <><div className="font-black uppercase text-lg">{flash.name}</div><div className="text-white/60 text-sm font-mono">{flash.code}</div><div className="label text-green-400 text-[10px] mt-1">{t("Checked in", "Adentro")}</div></> : <div className="font-bold">{flash.msg}</div>}
              </div>
            )}
            {!flash && <div className="absolute inset-0 flex items-center justify-center"><Icon name="qr-code" className="w-20 h-20 text-white/15" /></div>}
          </div>
          <form onSubmit={submitManual} className="flex gap-2"><input value={manual} onChange={(e) => setManual(e.target.value)} placeholder={t("Enter door code (PP-…)", "Código de puerta (PP-…)")} className="flex-1 bg-ink border border-white/12 rounded-xl px-3 py-3 text-sm text-white focus:outline-none focus:border-coral placeholder:text-white/35" /><button className="px-4 rounded-xl border border-white/15 text-white/80 text-sm font-bold hover:bg-white/5">{t("Check", "Validar")}</button></form>
          <p className="text-white/35 text-[11px] mt-3 leading-relaxed">{t("Type the code from the guest's invitation. Codes are issued in the Invitations module.", "Escribe el código de la invitación del cliente. Los códigos se emiten en el módulo Invitaciones.")}</p>
        </div>
      </div>
      {/* guest list */}
      <div className="lg:col-span-7">
        <div className="grid grid-cols-3 gap-3 mb-4">
          <div className="rounded-2xl border border-white/10 bg-card p-4 text-center"><div className="serif text-3xl text-green-400">{inside.length}</div><div className="label text-white/45 text-[9px]">{t("Inside", "Adentro")}</div></div>
          <div className="rounded-2xl border border-white/10 bg-card p-4 text-center"><div className="serif text-3xl text-coral">{pending.length}</div><div className="label text-white/45 text-[9px]">{t("Pending", "Pendientes")}</div></div>
          <div className="rounded-2xl border border-white/10 bg-card p-4 text-center"><div className="serif text-3xl text-gold-soft">{inside.reduce((s, g) => s + (g.party || 1), 0)}</div><div className="label text-white/45 text-[9px]">{t("Headcount", "Personas")}</div></div>
        </div>
        {visible.length === 0 ? (
          <div className="rounded-2xl border border-dashed border-white/15 p-10 text-center text-white/45 text-sm">
            <Icon name="qr-code" className="w-8 h-8 mx-auto mb-3 text-white/25" />
            {t("No invitations for tonight yet. Create them in the Invitations module — they appear here for check-in.", "Aún no hay invitaciones para hoy. Créalas en el módulo Invitaciones — aparecerán aquí para el check-in.")}
          </div>
        ) : (
          <div className="space-y-2 max-h-[420px] overflow-y-auto pr-1">
            {visible.map((g) => (
              <div key={g.id} className="flex items-center gap-3 p-3 rounded-xl border border-white/10 bg-card">
                <div className={"w-2.5 h-2.5 rounded-full shrink-0 " + (g.status === "in" ? "bg-green-400" : "bg-coral")}></div>
                <div className="flex-1 min-w-0"><div className="font-semibold text-sm truncate">{g.name} <span className="text-white/35 font-normal">×{g.party}</span></div><div className="text-white/45 text-xs font-mono">{g.code} · {g.date}</div></div>
                {g.status === "in" ? <span className="text-green-400 text-[11px] font-bold">{fmtAt(g.checkedAt)}</span>
                  : <button onClick={() => checkIn(g)} className="px-3 py-1.5 rounded-full bg-coral/15 border border-coral/40 text-coral text-[11px] font-bold uppercase tracking-wider hover:bg-coral hover:text-white transition-all">{t("Check in", "Entrar")}</button>}
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

/* ---------- DASHBOARD — real numbers from PPDB (no demo data) ---------- */
function AdminDashboard({ go }) {
  const t = useT(); const { lang } = useLang();
  const inv = useInvites();
  const inside = inv.filter((x) => x.status === "in");
  const pendingInv = inv.filter((x) => x.status === "active");
  const heads = inside.reduce((s, x) => s + (x.party || 1), 0);
  const menu = window.PPDB.getMenu();
  const liveItems = Object.values(menu).reduce((s, arr) => s + arr.length, 0);
  const stats = [
    ["scan-line", inside.length, t("Checked in", "Adentro"), "#5FBFA8", "door"],
    ["user-plus", pendingInv.length, t("Active invites", "Invitaciones activas"), "#FF6B5B", "invites"],
    ["users", heads, t("Guests inside", "Personas adentro"), "#9333EA", "door"],
    ["book-open", liveItems, t("Menu items live", "Items de menú activos"), "#CBA35C", "menus"],
  ];
  /* real activity: latest invite events */
  const feed = inv.slice(0, 6).map((x) => ({
    ic: x.status === "in" ? "scan-line" : x.status === "cancelled" ? "x-circle" : "user-plus",
    c: x.status === "in" ? "#5FBFA8" : x.status === "cancelled" ? "#777" : "#FF6B5B",
    txt: x.status === "in"
      ? t(`${x.name} checked in (${x.party})`, `${x.name} entró (${x.party})`)
      : x.status === "cancelled"
        ? t(`Invitation cancelled — ${x.name}`, `Invitación cancelada — ${x.name}`)
        : t(`Invitation issued — ${x.name} · ${x.code}`, `Invitación emitida — ${x.name} · ${x.code}`),
    w: x.date,
  }));
  const upcoming = (window.PP.MATCHDAYS || []).slice(0, 4);
  return (
    <div className="space-y-7">
      <div className="grid grid-cols-2 lg:grid-cols-4 gap-3">
        {stats.map(([ic, n, l, c, dest], i) => <button key={i} onClick={() => go(dest)} className="reveal rounded-2xl border border-white/10 bg-card p-5 text-left hover:border-coral/40 transition-all" data-d={(i % 3) + 1}><Icon name={ic} className="w-5 h-5 mb-3" style={{ color: c }} /><div className="text-3xl font-black leading-none">{n}</div><div className="label text-white/45 text-[9px] mt-1.5">{l}</div></button>)}
      </div>
      <div className="grid lg:grid-cols-12 gap-5">
        <div className="lg:col-span-7 rounded-2xl border border-white/10 bg-card p-6">
          <div className="flex items-center justify-between mb-4"><h3 className="text-lg font-black uppercase">{t("Upcoming events", "Próximos eventos")}</h3><button onClick={() => go("invites")} className="text-coral text-[11px] font-bold uppercase tracking-wider">{t("Create invitations", "Crear invitaciones")}</button></div>
          <div className="space-y-3">
            {upcoming.map((ev, i) => (
              <div key={i} className="flex items-center gap-4 rounded-xl border border-white/10 bg-ink p-4">
                <div className="w-10 h-10 rounded-lg bg-coral/12 border border-coral/30 flex items-center justify-center shrink-0"><Icon name="trophy" className="w-4 h-4 text-coral" /></div>
                <div className="flex-1 min-w-0"><div className="font-bold text-sm truncate">{ev.match}</div><div className="text-white/45 text-xs">{L(ev.date, lang)} · {ev.time}</div></div>
              </div>
            ))}
          </div>
        </div>
        <div className="lg:col-span-5 rounded-2xl border border-white/10 bg-card p-6">
          <h3 className="text-lg font-black uppercase mb-4">{t("Recent activity", "Actividad reciente")}</h3>
          {feed.length === 0 ? (
            <p className="text-white/40 text-sm leading-relaxed">{t("No activity yet. Issue your first invitation and it will show up here.", "Sin actividad aún. Emite tu primera invitación y aparecerá aquí.")}</p>
          ) : (
            <div className="space-y-3.5">
              {feed.map((f, i) => (
                <div key={i} className="flex items-start gap-3">
                  <div className="w-8 h-8 rounded-lg flex items-center justify-center shrink-0" style={{ background: f.c + "1f", border: "1px solid " + f.c + "55" }}><Icon name={f.ic} className="w-4 h-4" style={{ color: f.c }} /></div>
                  <div className="flex-1 min-w-0"><div className="text-sm text-white/80 leading-snug">{f.txt}</div><div className="text-white/35 text-[11px] mt-0.5">{f.w}</div></div>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   PINK PONY HUB — staff sign-in (email + password, roles).
   First run creates the master account; legacy PIN devices get a
   one-time migration to email+password. Accounts live in
   PPDB.accounts (hashed, cloud-synced via the "staff" collection).
   ============================================================ */
const HUB_INPUT = "w-full bg-ink border border-white/12 rounded-xl px-4 py-3.5 text-[15px] text-white focus:outline-none focus:border-coral transition-colors placeholder:text-white/30";
const HUB_LABEL = "label text-white/50 text-[10px] block mb-2 text-left";

function AdminGate({ onAuthed }) {
  const t = useT();
  const initialMode = () => window.PPDB.auth.needsSetup() ? "setup" : window.PPDB.auth.hasLegacyPin() ? "migrate" : "login";
  const [mode, setMode] = useState(initialMode);
  const [f, setF] = useState({ name: "", email: "", pass: "", pass2: "", pin: "" });
  const [err, setErr] = useState("");
  const [busy, setBusy] = useState(false);
  const set = (k, v) => setF((p) => ({ ...p, [k]: v }));

  // accounts syncing in from another device (cloud) flip setup -> login
  useEffect(() => {
    const sync = () => { if (mode !== "login" && window.PPDB.auth.hasAccounts()) setMode("login"); };
    window.addEventListener("pp:staff", sync);
    return () => window.removeEventListener("pp:staff", sync);
  }, [mode]);

  const validEmail = (e) => /.+@.+\..+/.test(e);

  const submit = async (e) => {
    e.preventDefault(); setErr(""); setBusy(true);
    try {
      if (mode === "login") {
        const sess = await window.PPDB.auth.login(f.email, f.pass);
        if (!sess) { setErr(t("Wrong email or password.", "Correo o contraseña incorrectos.")); set("pass", ""); return; }
        onAuthed();
      } else if (mode === "setup" || mode === "migrate") {
        if (!f.name.trim()) { setErr(t("Enter your name.", "Escribe tu nombre.")); return; }
        if (!validEmail(f.email)) { setErr(t("Enter a valid email.", "Escribe un correo válido.")); return; }
        if (f.pass.length < 8) { setErr(t("Password must be at least 8 characters.", "La contraseña debe tener al menos 8 caracteres.")); return; }
        if (f.pass !== f.pass2) { setErr(t("Passwords don't match.", "Las contraseñas no coinciden.")); return; }
        if (mode === "migrate") {
          const sess = await window.PPDB.auth.migrateLegacy(f.pin, { name: f.name.trim(), email: f.email, password: f.pass });
          if (!sess) { setErr(t("Current PIN is wrong.", "El PIN actual es incorrecto.")); return; }
          onAuthed();
        } else {
          await window.PPDB.auth.createAccount({ name: f.name.trim(), email: f.email, password: f.pass, role: "master" });
          await window.PPDB.auth.login(f.email, f.pass);
          onAuthed();
        }
      }
    } finally { setBusy(false); }
  };

  return (
    <div className="min-h-screen flex items-center justify-center px-6 pt-24 pb-16 relative overflow-hidden">
      <div className="absolute -top-24 left-1/2 -translate-x-1/2 w-[40rem] h-[24rem] bg-coral/10 rounded-full blur-[140px] pointer-events-none"></div>
      <div className="relative w-full max-w-md text-center fade-view">
        <img src={window.__asset ? window.__asset("assets/logo-pink-trimmed.png") : "assets/logo-pink-trimmed.png"} alt="Pink Pony Club" className="h-9 mx-auto mb-6 object-contain" />
        <h1 className="text-2xl md:text-3xl font-black uppercase tracking-wide mb-1.5">Pink Pony Hub</h1>
        <p className="text-white/50 text-sm mb-8">{t("Internal platform · Club Pink Pony, Doral", "Plataforma Interna · Club Pink Pony, Doral")}</p>

        {mode === "forgot" ? (
          <div className="rounded-3xl border border-white/12 bg-card p-7 text-left fade-view">
            <h2 className="text-lg font-black uppercase mb-3">{t("Reset your password", "Restablece tu contraseña")}</h2>
            <ul className="space-y-3 text-white/60 text-sm leading-relaxed mb-6">
              <li className="flex gap-2.5"><Icon name="users" className="w-4 h-4 text-coral shrink-0 mt-0.5" />{t("Ask a master account to reset it in Hub → Team & Access.", "Pídele a una cuenta master que la restablezca en Hub → Equipo y Accesos.")}</li>
              <li className="flex gap-2.5"><Icon name="message-circle" className="w-4 h-4 text-coral shrink-0 mt-0.5" />{t("Or contact the owner directly.", "O contacta directamente al dueño.")}</li>
            </ul>
            <button onClick={() => setMode("login")} className="w-full py-3 rounded-full border border-white/15 text-white/80 text-[12px] font-bold uppercase tracking-[0.14em] hover:bg-white/5">{t("Back to sign in", "Volver a iniciar sesión")}</button>
          </div>
        ) : (
          <form onSubmit={submit} className="rounded-3xl border border-white/12 bg-card p-7 space-y-4 text-left">
            {(mode === "setup" || mode === "migrate") && (
              <div className="rounded-xl border border-gold/25 bg-gold/5 px-4 py-3 text-white/65 text-[13px] leading-relaxed">
                {mode === "setup"
                  ? t("First time here — create the master account that controls the Hub.", "Primera vez — crea la cuenta master que controla el Hub.")
                  : t("Security upgrade: confirm your current PIN and create your master account (email + password).", "Mejora de seguridad: confirma tu PIN actual y crea tu cuenta master (correo + contraseña).")}
              </div>
            )}
            {mode === "migrate" && (<div><label className={HUB_LABEL}>{t("Current PIN", "PIN actual")}</label><input type="password" inputMode="numeric" value={f.pin} onChange={(e) => set("pin", e.target.value.replace(/\D/g, "").slice(0, 8))} className={HUB_INPUT} placeholder="••••" /></div>)}
            {(mode === "setup" || mode === "migrate") && (<div><label className={HUB_LABEL}>{t("Your name", "Tu nombre")}</label><input value={f.name} onChange={(e) => set("name", e.target.value)} className={HUB_INPUT} placeholder={t("Owner / Manager name", "Nombre del dueño / gerente")} /></div>)}
            <div><label className={HUB_LABEL}>Email</label><input type="email" autoComplete="username" value={f.email} onChange={(e) => set("email", e.target.value)} className={HUB_INPUT} placeholder="tu@email.com" /></div>
            <div><label className={HUB_LABEL}>{t("Password", "Contraseña")}</label><input type="password" autoComplete={mode === "login" ? "current-password" : "new-password"} value={f.pass} onChange={(e) => set("pass", e.target.value)} className={HUB_INPUT} placeholder="••••••••" /></div>
            {(mode === "setup" || mode === "migrate") && (<div><label className={HUB_LABEL}>{t("Confirm password", "Confirma la contraseña")}</label><input type="password" autoComplete="new-password" value={f.pass2} onChange={(e) => set("pass2", e.target.value)} className={HUB_INPUT} placeholder="••••••••" /></div>)}
            {err && <p className="text-coral text-xs font-semibold">{err}</p>}
            <button disabled={busy} className="gbtn w-full py-4 rounded-full text-white text-[13px] font-black uppercase tracking-[0.18em] disabled:opacity-50 transition-transform hover:scale-[1.01]" style={{ background: "linear-gradient(135deg,#FF2E88,#FF6B5B)", boxShadow: "0 10px 36px rgba(255,46,136,.4)" }}>
              {busy ? t("One moment…", "Un momento…") : mode === "login" ? t("Sign in", "Iniciar sesión") : t("Create account & enter", "Crear cuenta y entrar")}
            </button>
            {mode === "login" && <button type="button" onClick={() => setMode("forgot")} className="block mx-auto text-coral text-[13px] underline underline-offset-4 hover:text-white transition-colors">{t("Forgot your password?", "¿Olvidaste tu contraseña?")}</button>}
          </form>
        )}

        <p className="text-white/35 text-[12px] mt-6 leading-relaxed">{t("Authorized Club Pink Pony personnel only.", "Solo para personal autorizado del Club Pink Pony.")}<br />{t("By signing in you accept the internal use policies.", "Al ingresar aceptas las políticas de uso interno.")}</p>
      </div>
    </div>
  );
}

/* ---------- member portal preview (AdminMaster view) ---------- */
function MemberPortalPreview() {
  const [acc, setAcc] = useState(window.PP.ACCOUNT);
  return <div className="-mt-4"><Dashboard account={acc} setAccount={(a) => setAcc(a || window.PP.ACCOUNT)} go={(v) => window.__ppGo && window.__ppGo(v)} preview /></div>;
}

/* role → which Hub modules each role can open */
const ROLE_META = {
  master: { label: { en: "Master · Full access", es: "Master · Acceso total" }, can: () => true },
  manager: { label: { en: "Manager", es: "Gerente" }, can: (id) => id !== "team" },
  door: { label: { en: "Door team", es: "Equipo de puerta" }, can: (id) => ["dashboard", "door", "invites"].includes(id) },
};

function AdminPortal() {
  const t = useT(); const { lang } = useLang();
  const [authed, setAuthed] = useState(() => window.PPDB.auth.isAuthed());
  const [tab, setTab] = useState("dashboard");
  const [navOpen, setNavOpen] = useState(false);
  useReveal(tab);

  if (!authed) return <AdminGate onAuthed={() => setAuthed(true)} />;

  const sess = window.PPDB.auth.session() || { name: "Admin", role: "master" };
  const role = ROLE_META[sess.role] || ROLE_META.master;

  const groups = [
    { label: t("Operations", "Operaciones"), items: [
      ["dashboard", t("Dashboard", "Panel"), "layout-dashboard"],
      ["invites", t("Invitations", "Invitaciones"), "user-plus"],
      ["events", t("Events", "Eventos"), "calendar-plus"],
      ["door", t("Door / Scan", "Puerta / Escáner"), "qr-code"],
      ["floor", t("Floor Plan", "Floor Plan"), "layout-grid"],
      ["res", t("Reservations", "Reservas"), "calendar-check"],
    ] },
    { label: t("Sales & Money", "Ventas y Dinero"), items: [
      ["leads", t("Leads", "Leads"), "inbox"],
      ["ticketera", t("Ticketera", "Ticketera"), "ticket"],
      ["promoters", t("Promoters", "Promotores"), "megaphone"],
      ["cash", t("Cash Control", "Control de Caja"), "calculator"],
    ] },
    { label: t("People & Shows", "Personas y Shows"), items: [
      ["crm", t("CRM", "CRM"), "contact"],
      ["staff", t("Employees", "Empleados"), "users"],
      ["dancers", t("Dancers", "Dancers"), "sparkles"],
      ["shows", t("Shows", "Shows"), "drama"],
    ] },
    { label: t("Content", "Contenido"), items: [
      ["menus", t("Menus & Discounts", "Menús y Descuentos"), "book-open"],
    ] },
    { label: t("System", "Sistema"), items: [
      ["team", t("Team & Access", "Equipo y Accesos"), "shield"],
    ] },
    { label: t("All Portals", "Todos los Portales"), items: [
      ["pmember", t("Member Portal", "Portal Miembros"), "crown"],
      ["pcrew", t("Crew Apps", "Apps del Equipo"), "smartphone"],
    ] },
  ].map((g) => ({ ...g, items: g.items.filter(([id]) => role.can(id)) })).filter((g) => g.items.length > 0);
  const allItems = groups.flatMap((g) => g.items);
  // if the current tab isn't allowed for this role, snap to the first allowed one
  useEffect(() => { if (!allItems.some(([id]) => id === tab)) setTab(allItems[0][0]); }, [sess.role]);
  const current = allItems.find((x) => x[0] === tab) || allItems[0];

  const navTo = (id) => { setTab(id); setNavOpen(false); window.scrollTo({ top: 0, behavior: "auto" }); };

  const SideNav = ({ mobile }) => (
    <nav className={mobile ? "space-y-5" : "space-y-6 sticky top-28"}>
      {groups.map((g) => (
        <div key={g.label}>
          <div className="label text-white/35 text-[9px] px-3 mb-2">{g.label}</div>
          <div className="space-y-1">
            {g.items.map(([id, lbl, ic]) => (
              <button key={id} onClick={() => navTo(id)} className={"w-full flex items-center gap-3 px-3 py-2.5 rounded-xl text-[13px] font-semibold transition-all " + (tab === id ? "bg-coral text-white shadow-[0_8px_24px_-8px_rgba(255,107,91,.6)]" : "text-white/60 hover:text-white hover:bg-white/5")}>
                <Icon name={ic} className="w-4.5 h-4.5 shrink-0" style={{ width: 18, height: 18 }} />{lbl}
              </button>
            ))}
          </div>
        </div>
      ))}
    </nav>
  );

  return (
    <div className="pt-24 md:pt-28 pb-24 min-h-screen bg-[#08080a]">
      <div className="container">
        {/* header */}
        <div className="flex items-center justify-between gap-4 mb-7">
          <div className="flex items-center gap-3">
            <button onClick={() => setNavOpen(true)} className="lg:hidden w-10 h-10 rounded-xl border border-white/12 flex items-center justify-center text-white/70"><Icon name="menu" className="w-5 h-5" /></button>
            <div>
              <div className="label text-coral text-[10px] mb-1 flex items-center gap-2"><span className="w-1.5 h-1.5 rounded-full bg-green-400 pulse-dot"></span>{t("Live · Tonight", "En vivo · Hoy")}</div>
              <h1 className="text-3xl md:text-4xl font-black uppercase leading-none">{current[1]}</h1>
            </div>
          </div>
          <div className="flex items-center gap-3">
            <div className="hidden sm:flex items-center gap-2 px-3 py-2 rounded-full border border-white/12 bg-card"><div className="w-7 h-7 rounded-full bg-gradient-to-br from-coral to-grape flex items-center justify-center text-[11px] font-black text-white">{(sess.name || "A")[0].toUpperCase()}</div><div className="text-left leading-tight"><div className="text-xs font-bold">{sess.name || "Admin"}</div><div className="text-[10px] text-gold-soft">{L(role.label, lang)}</div></div></div>
            <button onClick={() => { window.PPDB.auth.close(); setAuthed(false); }} className="text-white/55 hover:text-white text-sm flex items-center gap-2"><Icon name="log-out" className="w-4 h-4" /><span className="hidden sm:inline">{t("Sign out", "Salir")}</span></button>
          </div>
        </div>

        <div className="grid lg:grid-cols-[230px_1fr] gap-7">
          <aside className="hidden lg:block"><SideNav /></aside>
          <div key={tab} className="fade-view min-w-0">
            {tab === "dashboard" && <AdminDashboard go={navTo} />}
            {tab === "invites" && <InvitesModule />}
            {tab === "leads" && <LeadsModule />}
            {tab === "events" && <EventsModule />}
            {tab === "floor" && <FloorPlanModule />}
            {tab === "ticketera" && <Ticketera />}
            {tab === "promoters" && <PromotersModule />}
            {tab === "cash" && <CashControlModule />}
            {tab === "door" && <DoorScanner />}
            {tab === "res" && <ReservationsModule />}
            {tab === "crm" && <CRMModule />}
            {tab === "staff" && <StaffModule />}
            {tab === "dancers" && <DancersModule />}
            {tab === "shows" && <ShowsModule />}
            {tab === "menus" && <MenusModule />}
            {tab === "team" && <TeamModule sess={sess} />}
            {tab === "pmember" && <MemberPortalPreview />}
            {tab === "pcrew" && <div className="-mt-6"><CrewView go={(v) => v === "admin" ? navTo("res") : (window.__ppGo && window.__ppGo(v))} embedded /></div>}
          </div>
        </div>
      </div>

      {/* mobile drawer */}
      {navOpen && (
        <div className="fixed inset-0 z-50 lg:hidden" onClick={() => setNavOpen(false)}>
          <div className="absolute inset-0 bg-black/70 backdrop-blur-sm"></div>
          <div className="absolute left-0 top-0 bottom-0 w-72 bg-ink border-r border-white/10 p-5 overflow-y-auto fade-view" onClick={(e) => e.stopPropagation()}>
            <div className="flex items-center justify-between mb-6"><img src={window.__asset ? window.__asset("assets/logo-white.png") : "assets/logo-white.png"} alt="Pink Pony Club" className="h-9" /><button onClick={() => setNavOpen(false)}><Icon name="x" className="w-6 h-6 text-white/60" /></button></div>
            <SideNav mobile />
          </div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { AdminPortal, AdminDashboard, FauxQR, ChargeButton, CardOnFile, BoxOffice, DoorScanner, AdminReservations });
