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

const { mockOptima, mockCheckPermissions, mockHandleApiError } = vi.hoisted(
  () => ({
    mockOptima: {
      company: { fetchMany: vi.fn() },
    },
    mockCheckPermissions: vi.fn(),
    mockHandleApiError: vi.fn(),
  }),
);

vi.mock("$lib", () => ({ optima: mockOptima }));
vi.mock("$lib/permissions", () => ({
  checkPermissions: mockCheckPermissions,
}));
vi.mock("$lib/optima-api/errorHandler", () => ({
  handleApiError: mockHandleApiError,
}));

import { load } from "./+page.server";

describe("companies +page.server.ts load", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("returns empty data when no access token", async () => {
    const result = await load({
      locals: {},
      url: new URL("http://localhost/companies"),
    } as any);

    expect(result).toMatchObject({
      companies: [],
      totalPages: 1,
      currentPage: 1,
      totalRecords: 0,
      search: "",
    });
  });

  it("fetches companies with pagination and search", async () => {
    mockOptima.company.fetchMany.mockResolvedValueOnce({
      data: [{ id: "c1" }],
      meta: {
        pagination: { totalPages: 3, currentPage: 2, totalRecords: 45 },
      },
    });
    mockCheckPermissions.mockResolvedValueOnce({ "companies.view": true });

    const result = await load({
      locals: { session: { accessToken: "tok" } },
      url: new URL("http://localhost/companies?page=2&search=acme"),
    } as any);

    expect(mockOptima.company.fetchMany).toHaveBeenCalledWith("tok", 2, "acme");
    expect(result).toMatchObject({
      companies: [{ id: "c1" }],
      totalPages: 3,
      currentPage: 2,
      totalRecords: 45,
      search: "acme",
    });
  });

  it("clamps page to minimum of 1", async () => {
    mockOptima.company.fetchMany.mockResolvedValueOnce({
      data: [],
      meta: {
        pagination: { totalPages: 1, currentPage: 1, totalRecords: 0 },
      },
    });
    mockCheckPermissions.mockResolvedValueOnce({});

    await load({
      locals: { session: { accessToken: "tok" } },
      url: new URL("http://localhost/companies?page=-5"),
    } as any);

    expect(mockOptima.company.fetchMany).toHaveBeenCalledWith("tok", 1, "");
  });

  it("handles API error gracefully when fetchMany fails", async () => {
    mockOptima.company.fetchMany.mockRejectedValueOnce(new Error("API down"));
    mockCheckPermissions.mockResolvedValueOnce({});

    const result = await load({
      locals: { session: { accessToken: "tok" } },
      url: new URL("http://localhost/companies"),
    } as any);

    // fetchMany is in a .catch() so it returns defaults
    expect(result).toMatchObject({
      companies: [],
      totalPages: 1,
    });
  });
});
