import test from "node:test";
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import { request, subscribeAuthenticationRequired } from "./api.js";

test("api helper turns network failures into a safe offline code", async () => {
  const source = await readFile(new URL("./api.js", import.meta.url), "utf8");

  assert.match(source, /pc_unreachable/);
  assert.match(source, /catch \(error\)/);
  assert.match(source, /throw new Error\("pc_unreachable"\)/);
  assert.doesNotMatch(source, /throw error/);
});

test("api helper sends the device cookie and CSRF marker on mutations", async () => {
  const calls = [];
  await request("/accounts", {
    method: "POST",
    body: { label: "Personal" },
    fetchImpl: async (...args) => {
      calls.push(args);
      return { ok: true, json: async () => ({ ok: true }) };
    }
  });

  assert.equal(calls.length, 1);
  assert.equal(calls[0][1].credentials, "include");
  assert.equal(calls[0][1].headers["x-code-remote-csrf"], "1");
});

test("api helper forwards cancellation and preserves a safe abort signal", async () => {
  const controller = new AbortController();
  let receivedSignal;
  const pending = request("/threads?search=old", {
    signal: controller.signal,
    fetchImpl: async (_url, options) => {
      receivedSignal = options.signal;
      return new Promise((_resolve, reject) => {
        options.signal.addEventListener("abort", () => {
          reject(new DOMException("cancelled", "AbortError"));
        }, { once: true });
      });
    }
  });

  controller.abort();

  await assert.rejects(pending, (error) => (
    error.name === "AbortError" && error.message === "request_aborted"
  ));
  assert.equal(receivedSignal, controller.signal);
});

test("api helper reports an expired or revoked device session without exposing a credential", async () => {
  let notified = 0;
  const unsubscribe = subscribeAuthenticationRequired(() => { notified += 1; });
  await assert.rejects(
    request("/accounts", {
      fetchImpl: async () => ({
        ok: false,
        status: 401,
        json: async () => ({ error: "authentication_required" })
      })
    }),
    /authentication_required/
  );
  unsubscribe();

  assert.equal(notified, 1);
});
