import { describe, expect, it, vi } from "vitest";

async function loadApi(apiUrl = "") {
  vi.resetModules();
  vi.stubEnv("VITE_API_URL", apiUrl);
  vi.stubEnv("VITE_API_PREFIX", "");
  return import("./api");
}

function jsonResponse(body: unknown, init?: ResponseInit) {
  return new Response(JSON.stringify(body), {
    status: 200,
    headers: { "Content-Type": "application/json" },
    ...init,
  });
}

describe("api helpers", () => {
  it("normalizes nullish API arrays", async () => {
    const { itemsOrEmpty } = await loadApi();

    expect(itemsOrEmpty(null)).toEqual([]);
    expect(itemsOrEmpty(undefined)).toEqual([]);
    expect(itemsOrEmpty(["a"])).toEqual(["a"]);
  });

  it("builds asset URLs from API base while preserving absolute URLs", async () => {
    const { assetUrl } = await loadApi("https://api.example.com");

    expect(assetUrl("/uploads/file.png")).toBe(
      "https://api.example.com/uploads/file.png",
    );
    expect(assetUrl("https://cdn.example.com/file.png")).toBe(
      "https://cdn.example.com/file.png",
    );
    expect(assetUrl(undefined)).toBe("");
  });

  it("fetches JSON with API base and throws response text on failure", async () => {
    const { getJSON } = await loadApi("https://api.example.com");
    const fetchMock = vi
      .fn()
      .mockResolvedValueOnce(jsonResponse({ ok: true }))
      .mockResolvedValueOnce(new Response("boom", { status: 500 }));
    vi.stubGlobal("fetch", fetchMock);

    await expect(getJSON("/api/resources")).resolves.toEqual({ ok: true });
    expect(fetchMock).toHaveBeenCalledWith(
      "https://api.example.com/api/resources",
    );
    await expect(getJSON("/api/fail")).rejects.toThrow("boom");
  });

  it("posts JSON with optional bearer token", async () => {
    const { postJSON } = await loadApi();
    const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ id: 1 }));
    vi.stubGlobal("fetch", fetchMock);

    await expect(
      postJSON("/api/admin/resources", { title: "Demo" }, "token-123"),
    ).resolves.toEqual({ id: 1 });

    expect(fetchMock).toHaveBeenCalledWith("/api/admin/resources", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer token-123",
      },
      body: JSON.stringify({ title: "Demo" }),
    });
  });
});
