import { describe, expect, test } from "bun:test";
import { turnstileProvider } from "../src/providers/turnstile.ts";
import { recaptchaProvider } from "../src/providers/recaptcha.ts";
import { hcaptchaProvider } from "../src/providers/hcaptcha.ts";

const okFetch =
  (payload: Record<string, unknown>) =>
  async (_url: string | URL | Request, init?: RequestInit) => {
    expect(init?.method).toBe("POST");
    expect(init?.headers).toMatchObject({ "content-type": "application/x-www-form-urlencoded" });
    return Response.json(payload);
  };

describe("hosted providers", () => {
  test("verifies Turnstile hostname and action", async () => {
    const provider = turnstileProvider({
      secretKey: "secret",
      expectedHostnames: ["example.test"],
      expectedAction: "signup",
      fetch: okFetch({ success: true, hostname: "example.test", action: "signup" }) as typeof fetch,
    });
    expect(await provider.verify({ action: "signup", providerToken: "token" })).toMatchObject({
      success: true,
      provider: "turnstile",
    });
  });

  test("maps provider duplicate failures", async () => {
    const provider = recaptchaProvider({
      secretKey: "secret",
      fetch: okFetch({ success: false, "error-codes": ["timeout-or-duplicate"] }) as typeof fetch,
    });
    expect(await provider.verify({ action: "login", providerToken: "token" })).toMatchObject({
      success: false,
      code: "already-used",
    });
  });

  test("sends hCaptcha site key when configured", async () => {
    let submitted = "";
    const provider = hcaptchaProvider({
      secretKey: "secret",
      siteKey: "site-key",
      fetch: (async (_url, init) => {
        submitted = String(init?.body);
        return Response.json({ success: true, hostname: "example.test" });
      }) as typeof fetch,
    });
    expect((await provider.verify({ action: "contact", providerToken: "token" })).success).toBe(
      true,
    );
    expect(submitted).toContain("sitekey=site-key");
  });
});
