// @vitest-environment node

import { beforeEach, describe, expect, it, vi } from "vitest";
import worker, {
  ADMIN_APP_SESSION_COOKIE,
  buildAccessDeniedHtml,
  createSignedAdminAppSession,
} from "./index";

const env = {
  ADMIN_APP_ACCESS_TOKEN: "super-secret-admin-app-token",
  ADMIN_APP_SESSION_SECRET: "worker-session-secret",
  ASSETS: {
    fetch: vi.fn(async () => new Response("<html>app</html>", { status: 200 })),
  },
};

describe("admin worker firewall", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("serves the admin access gate when no session cookie is present", async () => {
    const response = await worker.fetch(
      new Request("https://admin-panel.xtablo.com/", {
        headers: {
          accept: "text/html",
        },
      }),
      env
    );

    expect(response.status).toBe(401);
    await expect(response.text()).resolves.toContain("Internal Admin Access");
  });

  it("creates a signed app session cookie from a valid access token", async () => {
    const request = new Request("https://admin-panel.xtablo.com/__admin/access", {
      body: new URLSearchParams({ accessToken: env.ADMIN_APP_ACCESS_TOKEN }),
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
      },
      method: "POST",
    });

    const response = await worker.fetch(request, env);

    expect(response.status).toBe(302);
    expect(response.headers.get("location")).toBe("https://admin-panel.xtablo.com/");
    expect(response.headers.get("set-cookie")).toContain(`${ADMIN_APP_SESSION_COOKIE}=`);
  });

  it("allows authenticated requests through to static assets", async () => {
    const session = await createSignedAdminAppSession(env.ADMIN_APP_SESSION_SECRET);
    const request = new Request("https://admin-panel.xtablo.com/", {
      headers: {
        cookie: `${ADMIN_APP_SESSION_COOKIE}=${session}`,
      },
    });

    const response = await worker.fetch(request, env);

    expect(response.status).toBe(200);
    expect(env.ASSETS.fetch).toHaveBeenCalledOnce();
  });

  it("rejects invalid access tokens", async () => {
    const request = new Request("https://admin-panel.xtablo.com/__admin/access", {
      body: new URLSearchParams({ accessToken: "wrong-token" }),
      headers: {
        accept: "text/html",
        "Content-Type": "application/x-www-form-urlencoded",
      },
      method: "POST",
    });

    const response = await worker.fetch(request, env);

    expect(response.status).toBe(401);
    await expect(response.text()).resolves.toContain("Invalid app access token");
  });
});

describe("buildAccessDeniedHtml", () => {
  it("renders the access error when provided", () => {
    expect(buildAccessDeniedHtml("Bad token")).toContain("Bad token");
  });
});
