import assert from "node:assert/strict";
import { test } from "node:test";
import { createOpencodeProbe } from "../src/opencode.js";

function jsonResponse(status: number): Response {
  return new Response(JSON.stringify({}), {
    status,
    headers: { "content-type": "application/json" },
  });
}

test("no OPENCODE_URL -> ok:false without calling fetch", async () => {
  let called = false;
  const probe = createOpencodeProbe({
    opencodeUrl: undefined,
    opencodeUsername: "opencode",
    fetch: () => {
      called = true;
      return Promise.resolve(jsonResponse(200));
    },
  });
  const result = await probe.probe();
  assert.equal(result.ok, false);
  assert.equal(result.detail, "OPENCODE_URL not set");
  assert.equal(called, false);
});

test("2xx -> ok:true with no detail", async () => {
  const probe = createOpencodeProbe({
    opencodeUrl: "http://127.0.0.1:4242",
    opencodeUsername: "opencode",
    opencodeServerPassword: "pw",
    fetch: () => Promise.resolve(jsonResponse(200)),
  });
  const result = await probe.probe();
  assert.equal(result.ok, true);
  assert.equal(result.detail, undefined);
});

test("401 -> ok:false with url + status in detail", async () => {
  const probe = createOpencodeProbe({
    opencodeUrl: "http://127.0.0.1:4242",
    opencodeUsername: "opencode",
    opencodeServerPassword: "pw",
    fetch: () => Promise.resolve(jsonResponse(401)),
  });
  const result = await probe.probe();
  assert.equal(result.ok, false);
  assert.match(result.detail ?? "", /127\.0\.0\.1:4242/);
  assert.match(result.detail ?? "", /401/);
});

test("fetch throws (timeout/network) -> ok:false with error in detail", async () => {
  const probe = createOpencodeProbe({
    opencodeUrl: "http://127.0.0.1:4242",
    opencodeUsername: "opencode",
    fetch: () => Promise.reject(new Error("The operation was aborted")),
  });
  const result = await probe.probe();
  assert.equal(result.ok, false);
  assert.match(result.detail ?? "", /aborted/);
});

test("sends Basic auth header built from username + server password", async () => {
  let seenAuth: string | null = null;
  const probe = createOpencodeProbe({
    opencodeUrl: "http://127.0.0.1:4242",
    opencodeUsername: "customuser",
    opencodeServerPassword: "pw",
    fetch: (input, init) => {
      // hey-api passes headers on the Request input; fall back to init for safety.
      const headers = new Headers(input instanceof Request ? input.headers : init?.headers);
      seenAuth = headers.get("authorization") ?? new Headers(init?.headers).get("authorization");
      return Promise.resolve(jsonResponse(200));
    },
  });
  await probe.probe();
  const expected = "Basic " + Buffer.from("customuser:pw").toString("base64");
  assert.equal(seenAuth, expected);
});
