/**
 * A process-wide authorization catalog registry, mirroring `@wrnexus/db`'s
 * `client.ts` (`setDb`/`getDb`/`hasDb`). It exists for the same reason: app
 * middleware runs at module-eval time — `app/middleware/*.ts` registers
 * `authzMiddleware({ catalog, store, ... })` itself, an EAGER call (the same
 * shape as `logger.ts`'s `export default requestLogger({...})`), and it needs
 * the merged catalog *then*, before its own module body finishes running.
 * Passing it through `ctx` does not work at that point, so the framework
 * loads and merges every `app/authz/*.ts` declaration and stashes it here
 * before any other module can observe it:
 *
 *  - dev: `startServer` calls `loadAppAuthzCatalog` + `setAuthzCatalog`
 *    before middleware is resolved.
 *  - prod (the normal `wrnexus build` output): the generated entry statically
 *    imports a small `.authz-setup.ts` module FIRST — before any page, API,
 *    or middleware import — which calls `setAuthzCatalog` at ITS OWN module
 *    scope. ES modules evaluate every static import before the importing
 *    module's body runs, and evaluate sibling imports in declaration order,
 *    so import position is evaluation order: this guarantees the catalog
 *    exists before app middleware's own module body (which may read it
 *    eagerly) ever evaluates. `createProductionHandlers` (`prod.ts`) then
 *    repeats the merge as an idempotent second pass, mainly so a caller who
 *    bypasses the generated entry and invokes it directly still gets a
 *    catalog — for THAT path specifically, an eager module-scope read in
 *    middleware is only safe if the caller sets the catalog before importing
 *    the middleware itself, since no generated `.authz-setup.ts` runs first.
 *
 * The framework never installs `authzMiddleware` itself — the app always
 * chooses its own store and registers the middleware; this registry only
 * makes the merged catalog reachable when it does.
 */

import type { AuthzCatalog } from "./types.ts";

let catalog: AuthzCatalog | undefined;

/** Set the process-wide authorization catalog (called by the framework at boot). */
export function setAuthzCatalog(next: AuthzCatalog): AuthzCatalog {
  catalog = next;
  return next;
}

/** The process-wide authorization catalog. Throws if it hasn't been set. */
export function getAuthzCatalog(): AuthzCatalog {
  if (!catalog) {
    throw new Error(
      "WRN-AUTHZ-SETUP: no authorization catalog is configured. The dev server and " +
        "`wrnexus build`'s generated production entry both call setAuthzCatalog() before " +
        "any other module — including your app's middleware — evaluates. If you're seeing " +
        "this: (a) you're on a custom production entry that calls createProductionHandlers " +
        "directly instead of the generated one, so you must call setAuthzCatalog(catalog) " +
        "yourself before importing anything that reads it eagerly; or (b) you're outside " +
        "the normal boot path entirely (a standalone script or test) and must call " +
        "setAuthzCatalog(catalog) first.",
    );
  }
  return catalog;
}

/** Whether the process-wide authorization catalog has been set. */
export function hasAuthzCatalog(): boolean {
  return catalog !== undefined;
}
