"use client";
import { flash } from "../FlashMessages.js";
import { deserializeOperationMetadata } from "@open-mercato/shared/lib/commands/operationMetadata";
import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
import { pushOperation } from "../operations/store.js";
import { pushPartialIndexWarning } from "../indexes/store.js";
import { createScopedHeaderStack } from "./scopedHeaderStack.js";
const scopedHeaders = createScopedHeaderStack();
function mergeHeaders(base, scoped) {
  const headers = new Headers(base ?? {});
  for (const [key, value] of Object.entries(scoped)) {
    if (headers.has(key)) continue;
    headers.set(key, value);
  }
  return headers;
}
function readRedirectOverride(headers, headerName) {
  return headers.get(headerName) === "0";
}
async function withScopedApiHeaders(headers, run) {
  return scopedHeaders.withScopedHeaders(headers, run);
}
class UnauthorizedError extends Error {
  constructor(message = "Unauthorized") {
    super(message);
    this.status = 401;
    this.name = "UnauthorizedError";
  }
}
function redirectToSessionRefresh() {
  if (typeof window === "undefined") return;
  const current = window.location.pathname + window.location.search;
  if (window.location.pathname.startsWith("/api/auth")) return;
  if (/\/[^/]+\/portal(\/|$)/.test(window.location.pathname)) return;
  try {
    flash("Session expired. Redirecting to sign in\u2026", "warning");
    setTimeout(() => {
      window.location.href = `/api/auth/session/refresh?redirect=${encodeURIComponent(current)}`;
    }, 20);
  } catch {
  }
}
class ForbiddenError extends Error {
  constructor(message = "Forbidden") {
    super(message);
    this.status = 403;
    this.name = "ForbiddenError";
  }
}
let DEFAULT_FORBIDDEN_ROLES = ["admin"];
function setAuthRedirectConfig(cfg) {
  if (cfg?.defaultForbiddenRoles && cfg.defaultForbiddenRoles.length) {
    DEFAULT_FORBIDDEN_ROLES = [...cfg.defaultForbiddenRoles].map(String);
  }
}
function redirectToForbiddenLogin(options) {
  if (typeof window === "undefined") return;
  if (window.location.pathname.startsWith("/login")) return;
  if (/\/[^/]+\/portal(\/|$)/.test(window.location.pathname)) return;
  try {
    const current = window.location.pathname + window.location.search;
    const features = options?.requiredFeatures?.filter(Boolean) ?? [];
    const roles = options?.requiredRoles?.filter(Boolean) ?? [];
    const fallbackRoles = DEFAULT_FORBIDDEN_ROLES.filter(Boolean);
    const effectiveRoles = roles.length ? roles : fallbackRoles;
    const query = features.length ? `requireFeature=${encodeURIComponent(features.join(","))}` : effectiveRoles.length ? `requireRole=${encodeURIComponent(effectiveRoles.map(String).join(","))}` : "";
    const url = query ? `/login?${query}&redirect=${encodeURIComponent(current)}` : `/login?redirect=${encodeURIComponent(current)}`;
    flash("Insufficient permissions. Redirecting to login\u2026", "warning");
    setTimeout(() => {
      window.location.href = url;
    }, 60);
  } catch {
  }
}
async function apiFetch(input, init) {
  const originalFetch = typeof window !== "undefined" ? window.__omOriginalFetch : void 0;
  const fallbackFetch = globalThis.fetch;
  const baseFetch = originalFetch ?? fallbackFetch;
  if (!baseFetch) {
    return new Response(
      JSON.stringify({ error: "Fetch API is not available in this runtime" }),
      { status: 503, headers: { "content-type": "application/json" } }
    );
  }
  const scoped = scopedHeaders.resolveScopedHeaders();
  const mergedInit = Object.keys(scoped).length ? { ...init ?? {}, headers: mergeHeaders(init?.headers, scoped) } : init;
  const requestHeaders = new Headers(mergedInit?.headers);
  const disableUnauthorizedRedirect = readRedirectOverride(requestHeaders, "x-om-unauthorized-redirect");
  const disableForbiddenRedirect = readRedirectOverride(requestHeaders, "x-om-forbidden-redirect");
  const res = await baseFetch(input, mergedInit);
  const pathname = typeof window !== "undefined" ? window.location.pathname : "";
  const onLoginPage = pathname.startsWith("/login");
  const onPortalRoute = /\/[^/]+\/portal(\/|$)/.test(pathname);
  if (res.status === 401) {
    if (!onLoginPage && !onPortalRoute && !disableUnauthorizedRedirect) {
      redirectToSessionRefresh();
      throw new UnauthorizedError(await res.text().catch(() => "Unauthorized"));
    }
    return res;
  }
  if (res.status === 403) {
    let roles = null;
    let features = null;
    let payload = null;
    const aclData = await readJsonSafe(res.clone(), null);
    if (aclData && typeof aclData === "object") {
      if (Array.isArray(aclData.requiredRoles)) {
        roles = aclData.requiredRoles.map((r) => String(r));
      }
      if (Array.isArray(aclData.requiredFeatures)) {
        features = aclData.requiredFeatures.map((f) => String(f));
      }
      payload = aclData;
    }
    if (!onLoginPage && !onPortalRoute && !disableForbiddenRedirect) {
      const target = typeof input === "string" ? input : input instanceof URL ? input.toString() : typeof Request !== "undefined" && input instanceof Request ? input.url : "unknown";
      try {
        console.warn("[apiFetch] Forbidden response", {
          url: target,
          status: res.status,
          requiredRoles: roles,
          requiredFeatures: features,
          details: payload
        });
      } catch {
      }
      const hasAclHints = Boolean(roles && roles.length || features && features.length);
      if (hasAclHints) {
        redirectToForbiddenLogin({ requiredRoles: roles, requiredFeatures: features });
      }
      let msg = "Forbidden";
      if (aclData && typeof aclData === "object") {
        if (typeof aclData.error === "string") {
          msg = aclData.error;
        } else if (typeof aclData.message === "string") {
          msg = aclData.message;
        }
      } else {
        msg = await res.clone().text().catch(() => "Forbidden");
      }
      throw new ForbiddenError(msg);
    }
  }
  try {
    const header = res.headers.get("x-om-operation");
    const metadata = deserializeOperationMetadata(header);
    if (metadata) pushOperation(metadata);
  } catch {
  }
  try {
    const warningRaw = res.headers.get("x-om-partial-index");
    if (warningRaw) {
      const parsed = JSON.parse(warningRaw);
      if (parsed && typeof parsed === "object" && parsed.type === "partial_index") {
        const entity = typeof parsed.entity === "string" ? parsed.entity : String(parsed.entity ?? "");
        if (entity) {
          const baseCount = typeof parsed.baseCount === "number" ? parsed.baseCount : null;
          const indexedCount = typeof parsed.indexedCount === "number" ? parsed.indexedCount : null;
          const scope = parsed.scope === "global" ? "global" : "scoped";
          const entityLabel = typeof parsed.entityLabel === "string" && parsed.entityLabel.trim() ? parsed.entityLabel.trim() : entity;
          pushPartialIndexWarning({ entity, entityLabel, baseCount, indexedCount, scope });
        }
      }
    }
  } catch {
  }
  return res;
}
export {
  ForbiddenError,
  UnauthorizedError,
  apiFetch,
  redirectToForbiddenLogin,
  redirectToSessionRefresh,
  setAuthRedirectConfig,
  withScopedApiHeaders
};
//# sourceMappingURL=api.js.map
