// Admin workspace (adminsupport.usenudge.app / admin.html). Root access to the
// full triage board. Gated by a shared passcode (verified server-side against
// ADMIN_PASSCODE). The passcode gates the UI; the data endpoints are also gated
// by the CORS origin allowlist (the admin subdomain must be listed). Session is
// kept in sessionStorage so it clears when the tab closes.
const { useState: useStateAdmin, useEffect: useEffectAdmin } = React;

const ADMIN_FLAG = "ns_admin_ok";

function AdminLogin({ onOk }) {
  const [passcode, setPasscode] = useStateAdmin("");
  const [err, setErr] = useStateAdmin("");
  const [busy, setBusy] = useStateAdmin(false);

  // 401 = wrong passcode (the ONLY hard rejection). 200+ok = signed in.
  // Anything else (no /api on the static server -> 501/404/HTML, or a network
  // error) means there's no backend to check against: fall through to the demo,
  // exactly like every other integration here. In production the endpoint
  // exists, so a wrong passcode always 401s.
  async function submit(e) {
    e.preventDefault(); setErr("");
    if (!passcode.trim()) return setErr("Enter the admin passcode.");
    setBusy(true);
    try {
      const r = await fetch("/api/v1/admin/session", {
        method: "POST", headers: { "content-type": "application/json" },
        body: JSON.stringify({ passcode }),
      });
      setBusy(false);
      if (r.status === 401) return setErr("That passcode didn't work.");
      if (r.ok) {
        const d = await r.json().catch(() => null);
        // The signed token is what authorizes approvals (which write to Jira).
        if (d && d.ok) { enter(!d.demo, d.token); return; }
      }
      enter(false); // no usable backend -> demo mode
    } catch (e) { setBusy(false); enter(false); }
  }

  // enforced=false means ADMIN_PASSCODE isn't set (or there's no backend) — the
  // UI says so rather than implying the queue is protected.
  function enter(enforced, token) {
    try {
      sessionStorage.setItem(ADMIN_FLAG, "1");
      sessionStorage.setItem(ADMIN_FLAG + "_enforced", enforced ? "1" : "0");
    } catch (e) {}
    window.NS.admin.setToken(token || "");
    onOk();
  }

  return (
    <div className="gate">
      <div className="gate-card card">
        <div className="brand-lockup">
          <span className="brand-dots"><i></i><i></i><i></i></span>
          Nudge <span className="brand-sub admin-tag">Support · Admin</span>
        </div>
        <h1 className="gate-title">Admin sign in</h1>
        <p className="gate-sub">Root access to the full triage queue. Enter the team passcode.</p>
        <form onSubmit={submit} className="gate-form">
          <label className="gate-field">
            <span>Admin passcode</span>
            <input type="password" autoComplete="current-password" placeholder="••••••••"
              value={passcode} onChange={(e) => setPasscode(e.target.value)} />
          </label>
          {err && <div className="gate-err">{err}</div>}
          <button type="submit" className="btn btn-primary gate-submit" disabled={busy}>
            {busy ? "Checking…" : "Enter admin"}
          </button>
        </form>
      </div>
    </div>
  );
}

// Slack deep-links here as ?ticket=<pendingId|JIRA-KEY>. A pending id (p_…)
// means "review this"; a Jira key means "look at this on the board".
function focusFromUrl() {
  try { return new URLSearchParams(location.search).get("ticket") || ""; }
  catch (e) { return ""; }
}

function AdminApp() {
  const [authed, setAuthed] = useStateAdmin(() => { try { return !!sessionStorage.getItem(ADMIN_FLAG); } catch (e) { return false; } });
  const [theme, setTheme] = useStateAdmin(() => document.documentElement.getAttribute("data-theme") || "light");
  const focus = focusFromUrl();
  const [tab, setTab] = useStateAdmin(() => (focus && !/^p_/.test(focus) ? "triage" : "queue"));

  useEffectAdmin(() => { window.NS.seedIfEmpty(); }, []);
  useEffectAdmin(() => { document.documentElement.setAttribute("data-theme", theme); }, [theme]);

  const themeBtn = (
    <button className="icon-btn" title="Toggle theme" onClick={() => setTheme((t) => (t === "dark" ? "light" : "dark"))}>
      {theme === "dark" ? "☀" : "☾"}
    </button>
  );

  if (!authed) {
    return (
      <React.Fragment>
        <header className="topbar">
          <div className="brand-lockup"><span className="brand-dots"><i></i><i></i><i></i></span>Nudge <span className="brand-sub admin-tag">Admin</span></div>
          <div className="topbar-spacer" />{themeBtn}
        </header>
        <AdminLogin onOk={() => setAuthed(true)} />
      </React.Fragment>
    );
  }

  const signOut = () => {
    try { sessionStorage.removeItem(ADMIN_FLAG); sessionStorage.removeItem(ADMIN_FLAG + "_enforced"); } catch (e) {}
    window.NS.admin.setToken("");
    setAuthed(false);
  };
  let enforced = true;
  try { enforced = sessionStorage.getItem(ADMIN_FLAG + "_enforced") !== "0"; } catch (e) {}

  const TABS = [
    { key: "queue", label: "Validation queue" },
    { key: "triage", label: "In Jira" },
    { key: "settings", label: "Reminders" },
  ];

  return (
    <div className="app">
      <header className="topbar">
        <div className="brand-lockup"><span className="brand-dots"><i></i><i></i><i></i></span>Nudge <span className="brand-sub admin-tag">Support · Admin</span></div>
        <nav className="tabs">
          {TABS.map((t) => (
            <button key={t.key} className={"tab" + (tab === t.key ? " is-on" : "")} onClick={() => setTab(t.key)}>{t.label}</button>
          ))}
        </nav>
        <div className="topbar-spacer" />
        <span className="who-chip" title={enforced ? "" : "ADMIN_PASSCODE is not set — this surface is unprotected"}>
          {enforced ? "root access" : "root access · unprotected"}
        </span>
        <button className="btn btn-ghost btn-sm" onClick={signOut}>Sign out</button>
        {themeBtn}
      </header>
      <main className="main">
        {tab === "queue" && <PendingQueue focusId={/^p_/.test(focus) ? focus : ""} />}
        {tab === "triage" && <TriageBoard focusKey={!/^p_/.test(focus) ? focus : ""} />}
        {tab === "settings" && <ReminderSettings />}
      </main>
      <AdminToast />
    </div>
  );
}

// Minimal toast so approve/reject/save give feedback. window.fireToast is the
// same hook the customer app exposes.
function AdminToast() {
  const [msg, setMsg] = useStateAdmin("");
  useEffectAdmin(() => {
    window.fireToast = (m) => { setMsg(m); setTimeout(() => setMsg(""), 3200); };
    return () => { window.fireToast = () => {}; };
  }, []);
  if (!msg) return null;
  return <div className="nudge-toast"><span className="nudge-toast-dot" />{msg}</div>;
}

ReactDOM.createRoot(document.getElementById("root")).render(<AdminApp />);
