// Admin API client. Every privileged call carries the signed session token that
// /api/v1/admin/session hands back (see api/_lib/adminauth.js).
//
// Degradation, in the project's usual shape: when there's no backend or no store
// (`no_store`), the admin workspace falls back to the LOCAL ticket mirror, so the
// creds-free demo still shows a validation queue. `live` tells the UI which one
// it's looking at, because a per-browser queue is not a real queue.

(function () {
  const TOKEN_KEY = "ns_admin_token";

  function token() { try { return sessionStorage.getItem(TOKEN_KEY) || ""; } catch (e) { return ""; } }
  function setToken(t) { try { t ? sessionStorage.setItem(TOKEN_KEY, t) : sessionStorage.removeItem(TOKEN_KEY); } catch (e) {} }

  function headers() {
    const h = { "content-type": "application/json" };
    const t = token();
    if (t) h.authorization = "Bearer " + t;
    return h;
  }

  async function req(path, init) {
    const r = await fetch(path, Object.assign({ headers: headers() }, init));
    const body = await r.json().catch(() => ({}));
    return { status: r.status, ok: r.ok, body };
  }

  // ---- pending queue ------------------------------------------------------
  // Local fallback: tickets the customer client mirrored with stage "pending".
  function localPending() {
    return window.NS.tickets.all()
      .map((t) => window.NS.normalizeTicket(t))
      .filter((t) => t.stage === "pending")
      .map((t) => Object.assign({}, t, { id: t.pendingId || t.key, ref: t.key }));
  }

  async function listPending() {
    try {
      const r = await req("/api/v1/admin/pending", { method: "GET" });
      if (r.ok && r.body.live) return { live: true, pending: r.body.pending };
      if (r.status === 401) return { live: false, pending: [], error: "admin_required" };
    } catch (e) { /* no backend */ }
    return { live: false, pending: localPending() };
  }

  // action: "approve" | "reject"
  async function decide(id, action, opts) {
    const payload = Object.assign({ id, action }, opts || {});
    try {
      const r = await req("/api/v1/admin/pending", { method: "POST", body: JSON.stringify(payload) });
      if (r.ok) return r.body;
      if (r.body && r.body.error) return Object.assign({ ok: false }, r.body);
    } catch (e) { /* no backend */ }
    return demoDecide(id, action, opts);
  }

  // Demo: mutate the local mirror so the queue visibly drains, and be honest
  // that nothing reached Jira.
  function demoDecide(id, action, opts) {
    const t = window.NS.tickets.all().find((x) => (x.pendingId || x.key) === id);
    if (!t) return { ok: false, error: "not_found" };
    if (action === "reject") {
      window.NS.tickets.upsert(Object.assign({}, t, { stage: "rejected", updatedAt: Date.now() }));
      return { ok: true, action: "rejected", id, demo: true };
    }
    const sev = (opts && opts.severity) || t.severity;
    const dest = (opts && opts.destination) || (["SEV1", "SEV2"].indexOf(sev) >= 0 ? "sprint" : "backlog");
    window.NS.tickets.upsert(Object.assign({}, t, { stage: "filed", severity: sev, updatedAt: Date.now() }));
    return { ok: true, action: "approved", id, key: t.key, severity: sev, destination: dest,
             placement: { placed: "none", reason: "demo — no Jira configured" }, demo: true };
  }

  // ---- settings -----------------------------------------------------------
  async function getSettings() {
    try {
      const r = await req("/api/v1/admin/settings", { method: "GET" });
      if (r.ok) return r.body;
    } catch (e) {}
    return { ok: true, live: false, settings: window.NS.DEFAULT_SETTINGS };
  }

  async function putSettings(patch) {
    try {
      const r = await req("/api/v1/admin/settings", { method: "PUT", body: JSON.stringify(patch) });
      return r.body;
    } catch (e) { return { ok: false, error: "unreachable" }; }
  }

  window.NS = Object.assign(window.NS || {}, {
    admin: { token, setToken, listPending, decide, getSettings, putSettings },
    // Mirrors api/_lib/store.js DEFAULT_SETTINGS — used when there's no backend.
    DEFAULT_SETTINGS: {
      reminders: {
        SEV1: { etaMinutes: 30, remindEveryMinutes: 60 },
        SEV2: { etaMinutes: 120, remindEveryMinutes: 240 },
        SEV3: { etaMinutes: 480, remindEveryMinutes: 480 },
        SEV4: { etaMinutes: 2880, remindEveryMinutes: 2880 },
      },
      accounts: {},
      routing: { SEV1: "sprint", SEV2: "sprint", SEV3: "backlog", SEV4: "backlog" },
    },
  });
})();
