import { afterEach, beforeEach, describe, expect, it } from "vitest";

import {
  DELETE as deleteSession,
  GET as getSession,
  POST as createSession,
} from "../auth/session/route";

describe("auth session API", () => {
  const originalApiKey = process.env.API_ACCESS_KEY;
  const originalAuthDisabled = process.env.API_AUTH_DISABLED;

  beforeEach(() => {
    process.env.API_ACCESS_KEY = "test-key";
    process.env.API_AUTH_DISABLED = "false";
  });

  afterEach(() => {
    process.env.API_ACCESS_KEY = originalApiKey;
    process.env.API_AUTH_DISABLED = originalAuthDisabled;
  });

  it("creates an HttpOnly browser session after validating the access key", async () => {
    const response = await createSession(request({ api_access_key: "test-key" }));
    const body = (await response.json()) as { authenticated: boolean };
    const setCookie = response.headers.get("set-cookie") ?? "";

    expect(response.status).toBe(200);
    expect(body.authenticated).toBe(true);
    expect(setCookie).toContain("geo_api_session=");
    expect(setCookie).toContain("HttpOnly");
    expect(setCookie).toMatch(/SameSite=Lax/i);
    expect(setCookie).toContain("Path=/");
    expect(setCookie).not.toContain("test-key");
  });

  it("rejects invalid access keys without setting a session cookie", async () => {
    const response = await createSession(request({ api_access_key: "wrong" }));

    expect(response.status).toBe(401);
    expect(response.headers.get("set-cookie")).toBeNull();
  });

  it("reports the current browser session state", async () => {
    const login = await createSession(request({ api_access_key: "test-key" }));
    const cookie = login.headers.get("set-cookie")?.split(";")[0] ?? "";

    const anonymous = await getSession(new Request("http://localhost/api/auth/session"));
    const authenticated = await getSession(
      new Request("http://localhost/api/auth/session", {
        headers: { cookie },
      }),
    );

    await expect(anonymous.json()).resolves.toEqual({ authenticated: false });
    await expect(authenticated.json()).resolves.toEqual({ authenticated: true });
  });

  it("clears the browser session cookie", async () => {
    const response = await deleteSession(
      new Request("http://localhost/api/auth/session", { method: "DELETE" }),
    );
    const setCookie = response.headers.get("set-cookie") ?? "";

    expect(response.status).toBe(200);
    await expect(response.json()).resolves.toEqual({ authenticated: false });
    expect(setCookie).toContain("geo_api_session=");
    expect(setCookie).toContain("Max-Age=0");
    expect(setCookie).toContain("HttpOnly");
  });
});

function request(body: unknown) {
  return new Request("http://localhost/api/auth/session", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify(body),
  });
}
