import { describe, expect, spyOn, test } from "bun:test";
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { buildRouter } from "../src/index.ts";

function appWithAuthz(files: Record<string, string>): string {
  const root = mkdtempSync(join(tmpdir(), "wrnexus-authz-"));
  const dir = join(root, "app", "authz");
  mkdirSync(dir, { recursive: true });
  mkdirSync(join(root, "app", "pages"), { recursive: true });
  for (const [name, body] of Object.entries(files)) writeFileSync(join(dir, name), body, "utf8");
  return join(root, "app");
}

describe("app/authz discovery", () => {
  test("collects .ts and .js declarations by filename", () => {
    const appDir = appWithAuthz({
      "blog.ts": "export default {};",
      "billing.js": "export default {};",
    });
    const router = buildRouter(appDir);
    expect(router.authz.map((entry) => entry.name).sort()).toEqual(["billing", "blog"]);
  });

  test("ignores non-module files", () => {
    const appDir = appWithAuthz({ "blog.ts": "export default {};", "notes.md": "# hi" });
    expect(buildRouter(appDir).authz.map((entry) => entry.name)).toEqual(["blog"]);
  });

  test("skips unsafe names", () => {
    const appDir = appWithAuthz({
      "ok.ts": "export default {};",
      "bad name!.ts": "export default {};",
    });
    expect(buildRouter(appDir).authz.map((entry) => entry.name)).toEqual(["ok"]);
  });

  test("an app with no authz directory yields an empty list", () => {
    const root = mkdtempSync(join(tmpdir(), "wrnexus-authz-none-"));
    mkdirSync(join(root, "app", "pages"), { recursive: true });
    expect(buildRouter(join(root, "app")).authz).toEqual([]);
  });

  test("quietly skips generated permissions.gen.ts without warning", () => {
    const appDir = appWithAuthz({
      "permissions.gen.ts": "export type Foo = 1;",
      "blog.ts": "export default {};",
    });
    const warnSpy = spyOn(console, "warn").mockImplementation(() => {});
    try {
      const router = buildRouter(appDir);
      expect(router.authz.map((entry) => entry.name)).toEqual(["blog"]);
      expect(warnSpy).not.toHaveBeenCalled();
    } finally {
      warnSpy.mockRestore();
    }
  });

  test("skips permissions.gen.js too, while a legitimately named declaration is still discovered", () => {
    const appDir = appWithAuthz({
      "permissions.gen.js": "export const x = 1;",
      "billing.js": "export default {};",
    });
    expect(buildRouter(appDir).authz.map((entry) => entry.name)).toEqual(["billing"]);
  });
});
