/// <reference types="bun-types" />
/**
 * requireBearer tests.
 *
 * Covers: valid bearer, missing header, lowercase "bearer", whitespace-
 * only token, empty token, wrong token, case-sensitive header lookup
 * for "authorization", and a constant-time-compare sanity check
 * (matched + byte-flipped both compared, no early-exit timing leak).
 */
import { describe, expect, it } from "bun:test";
import { requireBearer } from "./auth.js";

const TOKEN = "super-secret-token-xyz";

function reqWith(headers: Record<string, string>): Request {
  return new Request("http://localhost/mcp", { method: "POST", headers });
}

describe("requireBearer", () => {
  it("returns null when the bearer matches", () => {
    const req = reqWith({ Authorization: `Bearer ${TOKEN}` });
    expect(requireBearer(req, TOKEN)).toBeNull();
  });

  it("returns 401 when the Authorization header is missing", async () => {
    const req = reqWith({});
    const res = requireBearer(req, TOKEN);
    expect(res).not.toBeNull();
    expect(res?.status).toBe(401);
  });

  it("accepts lowercase 'bearer' prefix (case-insensitive)", () => {
    const req = reqWith({ Authorization: `bearer ${TOKEN}` });
    expect(requireBearer(req, TOKEN)).toBeNull();
  });

  it("rejects a whitespace-only token", () => {
    const req = reqWith({ Authorization: "Bearer    " });
    const res = requireBearer(req, TOKEN);
    expect(res?.status).toBe(401);
  });

  it("rejects an empty token after the Bearer prefix", () => {
    const req = reqWith({ Authorization: "Bearer " });
    const res = requireBearer(req, TOKEN);
    expect(res?.status).toBe(401);
  });

  it("rejects a wrong token", () => {
    const req = reqWith({ Authorization: `Bearer not-${TOKEN}` });
    const res = requireBearer(req, TOKEN);
    expect(res?.status).toBe(401);
  });

  it("performs case-insensitive header lookup ('authorization')", () => {
    // Fetch Headers is already case-insensitive; verify we rely on that
    // rather than a strict-case lookup.
    const req = reqWith({ authorization: `Bearer ${TOKEN}` });
    expect(requireBearer(req, TOKEN)).toBeNull();
  });

  it("compares constant-time: matched + byte-flipped both reach the comparator", () => {
    // One matched, one byte-flipped at the tail. Both must be evaluated
    // by timingSafeEqual (i.e. neither short-circuits on prefix match).
    const matched = TOKEN;
    const flipped = TOKEN.slice(0, -1) + (TOKEN.endsWith("z") ? "a" : "z");
    expect(matched).not.toBe(flipped);
    expect(matched.length).toBe(flipped.length);

    const ok = requireBearer(reqWith({ Authorization: `Bearer ${matched}` }), TOKEN);
    const bad = requireBearer(reqWith({ Authorization: `Bearer ${flipped}` }), TOKEN);

    expect(ok).toBeNull();
    expect(bad?.status).toBe(401);

    // Sanity: length-mismatch tokens also fail (no padding bypass).
    const short = requireBearer(
      reqWith({ Authorization: `Bearer ${TOKEN.slice(0, 5)}` }),
      TOKEN,
    );
    expect(short?.status).toBe(401);

    const longer = requireBearer(
      reqWith({ Authorization: `Bearer ${TOKEN}extra` }),
      TOKEN,
    );
    expect(longer?.status).toBe(401);
  });

  it("rejects when the expected token itself is empty/whitespace", () => {
    const req = reqWith({ Authorization: `Bearer ${TOKEN}` });
    expect(requireBearer(req, "")?.status).toBe(401);
    expect(requireBearer(req, "   ")?.status).toBe(401);
  });
});
