// Tiny fetch helper used by app.jsx for every HTTP call.
// Reads base URL + token from window globals injected by index.html.
//
// Errors: throws on non-2xx. Callers can .catch() to show a friendly
// failure (e.g. the undo bar's "Couldn't send that" copy).
//
// 401 special case: with indefinite-lifetime JWTs, the only realistic
// way to get a 401 is operator-side action (server-side jwt_secret
// rotation, account revoked from tenant, manual localStorage wipe). In
// all those cases the right UX is "drop the dead token and re-route
// through Google". We do that here so every caller doesn't have to
// reimplement it. The fetch still throws so in-flight requests fail
// cleanly — but the redirect kicks off before the .catch fires, so
// callers won't see anything render.

async function kxLogout({ redirect = true } = {}) {
  try {
    localStorage.removeItem("kx_token");
    localStorage.removeItem("kx_jwt");
  } catch (_) { /* private mode / disabled storage — ignore */ }
  window.KX_TOKEN = null;
  if (redirect) {
    // Send the operator back through Google so they get a fresh token.
    // /auth/google/start sets the OAuth state cookie and 302s to Google;
    // the callback redirects back to the PWA root with ?token=... which
    // the bootstrap in index.html stores + strips from the URL.
    window.location.href = window.KX_API_BASE.replace(/\/api\/v1$/, '') + "/auth/google/start";
  }
}
window.kxLogout = kxLogout;

async function kxApi(path, opts = {}) {
  // FormData uploads must let the browser set the Content-Type
  // (multipart boundary). Only force JSON for non-FormData bodies.
  const isFormData = typeof FormData !== 'undefined' && opts.body instanceof FormData;
  const headers = {
    ...(isFormData ? {} : { "Content-Type": "application/json" }),
    ...(opts.headers || {}),
  };
  if (window.KX_TOKEN) {
    headers["Authorization"] = "Bearer " + window.KX_TOKEN;
  }
  const res = await fetch(window.KX_API_BASE + path, { ...opts, headers });
  if (res.status === 401 && window.KX_TOKEN) {
    // Token is dead. Don't silently render mock data — clear it and
    // re-route through Google. Throw so the in-flight call still
    // resolves to its catch branch (the redirect will arrive a tick
    // later; callers won't see anything render meanwhile).
    kxLogout({ redirect: true });
    throw new Error("API 401 " + path + " — re-authenticating");
  }
  if (!res.ok) throw new Error("API " + res.status + " " + path);
  // Some endpoints (e.g. /pause action acks) return empty body — guard.
  const ctype = res.headers.get("content-type") || "";
  if (!ctype.includes("application/json")) return null;
  return res.json();
}
window.kxApi = kxApi;
