/**
 * Zeq Safe Fetch — graceful wrapper around the live Zeq API.
 *
 * Routes that aren't deployed yet (e.g. /api/chain/{slug}/append,
 * /api/zeq/settle, /api/zeq/compliance/verify, /api/contracts/generate,
 * /api/usage, /api/observer*) return 404 today. This helper surfaces them
 * as `{ ok:false, notDeployed:true }` so the UI can show a calm "coming
 * online when the framework ships it" notice instead of a red error.
 *
 * Mirrors src/api/safeFetch.ts in the VS Code extension so both surfaces
 * behave identically.
 *
 * @version 1.287.27
 * @license CC BY 4.0 — Zeq. H / Zeq 1.287 Hz Limited
 */
(function () {
  "use strict";

  const KNOWN_UNBUILT = new Set([
    "/api/zeq/settle",
    "/api/zeq/compliance/verify",
    "/api/chain/append",
    "/api/contracts/generate",
    "/api/usage",
    "/api/observer",
    "/api/observer/recent",
  ]);

  function isUnbuiltPath(path) {
    const norm = (path || "").split("?")[0];
    if (KNOWN_UNBUILT.has(norm)) return true;
    for (const k of KNOWN_UNBUILT) if (norm.startsWith(k + "/")) return true;
    // Also catch /api/chain/<slug>/append shape (chain-append per machine)
    if (/^\/api\/chain\/[^/]+\/append$/.test(norm)) return true;
    return false;
  }

  /**
   * @param {string} url - absolute URL.
   * @param {RequestInit & {timeoutMs?:number}} [init]
   * @returns {Promise<{ok:boolean,status:number,data:any|null,notDeployed?:boolean,error?:string}>}
   */
  async function safeFetch(url, init) {
    const timeoutMs = (init && init.timeoutMs) || 8000;
    const ctrl = new AbortController();
    const t = setTimeout(() => ctrl.abort(), timeoutMs);
    try {
      const res = await fetch(url, Object.assign({}, init, { signal: ctrl.signal }));
      if (res.status === 404) {
        let path = "";
        try { path = new URL(url).pathname; } catch (_) { /* relative */ }
        const notDeployed = isUnbuiltPath(path);
        return { ok: false, status: 404, data: null, notDeployed, error: notDeployed ? "Backend route not deployed yet" : "Not found" };
      }
      if (!res.ok) {
        let text = "";
        try { text = await res.text(); } catch (_) { /* ignore */ }
        return { ok: false, status: res.status, data: null, error: (text || "").slice(0, 200) || ("HTTP " + res.status) };
      }
      let data = null;
      try { data = await res.json(); } catch (_) { /* non-JSON body */ }
      return { ok: true, status: res.status, data };
    } catch (e) {
      return { ok: false, status: 0, data: null, error: (e && e.message) || "Network error" };
    } finally {
      clearTimeout(t);
    }
  }

  /** Surface a friendly notice if the call missed; no-op on success. */
  function reportSafeResult(label, r) {
    if (!r || r.ok) return;
    let msg;
    if (r.notDeployed) msg = label + ": backend route not deployed yet — coming online when the framework ships it.";
    else if (r.status === 401) msg = label + ": sign in first.";
    else msg = label + ": " + (r.error || ("HTTP " + r.status));
    try { console.warn("[Zeq]", msg); } catch (_) {}
  }

  window.ZeqSafeFetch = { safeFetch, reportSafeResult, isUnbuiltPath };
  if (typeof module !== "undefined" && module.exports) module.exports = window.ZeqSafeFetch;
})();
