import assert from "node:assert/strict";
import { test } from "bun:test";

import { createOpenFgaAuthorizer } from "./openfga-authorization.ts";

test("OpenFGA shadow mode is normalized to enforce and denies without a tuple", async () => {
  const calls: Array<{ path: string; method: string }> = [];
  const authorizer = createOpenFgaAuthorizer({
    env: { HWLAB_OPENFGA_MODE: "shadow", HWLAB_OPENFGA_API_URL: "http://openfga.test" },
    fetchImpl: async (url: string | URL, init: RequestInit = {}) => {
      const parsed = new URL(String(url));
      calls.push({ path: parsed.pathname, method: init.method ?? "GET" });
      if (parsed.pathname === "/healthz") return jsonResponse({}, 200);
      if (parsed.pathname === "/stores") return jsonResponse({ id: "store-shadow" }, 201);
      if (parsed.pathname === "/stores/store-shadow/authorization-models") return jsonResponse({ authorization_model_id: "model-shadow" }, 201);
      if (parsed.pathname === "/stores/store-shadow/check") return jsonResponse({ allowed: false }, 200);
      return jsonResponse({ error: "unexpected path" }, 404);
    }
  });

  const decision = await authorizer.check({
    actor: { id: "usr_shadow", role: "user" },
    relation: "can_use",
    object: "tool:hwpod"
  });

  assert.equal(decision.mode, "enforce");
  assert.equal(decision.allowed, false);
  assert.equal(decision.fgaAllowed, false);
  assert.equal(decision.decisionSource, "openfga");
  assert.deepEqual(calls.map((call) => call.path), [
    "/healthz",
    "/stores",
    "/stores/store-shadow/authorization-models",
    "/stores/store-shadow/check",
    "/stores/store-shadow/check"
  ]);
});

function jsonResponse(body: unknown, status: number) {
  return new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
}
