import { describe, it, expect, vi, beforeEach } from "vitest";
import { apiRequest, apiGet, apiPost } from "../client.js";

vi.mock("../http.js", () => ({
  requestHttp: vi.fn(),
}));

import { requestHttp } from "../http.js";

describe("apiRequest", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("returns ok=true on HTTP success with data.status=true", async () => {
    requestHttp.mockResolvedValue({
      response: { ok: true, status: 200 },
      data: { status: true, data: { items: [] } },
      meta: { url: "/test", method: "GET" },
    });

    const result = await apiRequest("GET", "/test");

    expect(result.ok).toBe(true);
    expect(result.data.status).toBe(true);
    expect(result.meta.url).toBe("/test");
  });

  it("returns ok=false on HTTP error", async () => {
    requestHttp.mockResolvedValue({
      response: { ok: false, status: 500 },
      data: { message: "Server error" },
      meta: { url: "/test", method: "GET" },
    });

    const result = await apiRequest("GET", "/test");

    expect(result.ok).toBe(false);
    expect(result.error.type).toBe("http_error");
    expect(result.error.statusCode).toBe(500);
  });

  it("returns ok=false on API error (data.status=false)", async () => {
    requestHttp.mockResolvedValue({
      response: { ok: true, status: 200 },
      data: { status: false, msg: "Invalid field", error_alias: "bad_input" },
      meta: { url: "/test", method: "POST" },
    });

    const result = await apiRequest("POST", "/test", { name: "x" });

    expect(result.ok).toBe(false);
    expect(result.error.type).toBe("api_error");
    expect(result.error.errorAlias).toBe("bad_input");
  });

  it("returns timeout on AbortError", async () => {
    requestHttp.mockRejectedValue(new DOMException("Aborted", "AbortError"));

    const result = await apiRequest("GET", "/test");

    expect(result.ok).toBe(false);
    expect(result.error.type).toBe("timeout");
  });

  it("returns network_error on generic throw", async () => {
    requestHttp.mockRejectedValue(new Error("Connection refused"));

    const result = await apiRequest("GET", "/test");

    expect(result.ok).toBe(false);
    expect(result.error.type).toBe("network_error");
  });
});

describe("apiGet", () => {
  it("calls apiRequest with GET method", async () => {
    requestHttp.mockResolvedValue({
      response: { ok: true, status: 200 },
      data: { status: true },
      meta: {},
    });

    await apiGet("/areas");

    expect(requestHttp).toHaveBeenCalledWith("GET", "/areas", null, undefined);
  });
});

describe("apiPost", () => {
  it("calls apiRequest with POST method and body", async () => {
    requestHttp.mockResolvedValue({
      response: { ok: true, status: 200 },
      data: { status: true },
      meta: {},
    });

    await apiPost("/areas", { name: "Kitchen" });

    expect(requestHttp).toHaveBeenCalledWith("POST", "/areas", { name: "Kitchen" }, undefined);
  });
});
