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

const getUserMock = vi.fn();
const findPersistedOidcUserMock = vi.fn();
const removeUserMock = vi.fn();
const shouldStartLoginRedirectMock = vi.fn();
const shouldSuppressDevelopmentSessionRedirectMock = vi.fn();

vi.mock("./auth", () => ({
  userManager: {
    getUser: (...args: unknown[]) => getUserMock(...args),
    removeUser: (...args: unknown[]) => removeUserMock(...args),
  },
}));

vi.mock("./oidcStorage", () => ({
  findPersistedOidcUser: (...args: unknown[]) =>
    findPersistedOidcUserMock(...args),
}));

vi.mock("../../../common/core/auth", () => ({
  shouldStartLoginRedirect: (...args: unknown[]) =>
    shouldStartLoginRedirectMock(...args),
}));

vi.mock("../../../common/core/session", () => ({
  shouldSuppressDevelopmentSessionRedirect: (...args: unknown[]) =>
    shouldSuppressDevelopmentSessionRedirectMock(...args),
}));

describe("apiClient", () => {
  beforeEach(() => {
    vi.resetModules();
    vi.stubEnv("MODE", "test");
    (
      window as Window & typeof globalThis & { _IS_TEST_MODE?: boolean }
    )._IS_TEST_MODE = true;
    window.localStorage.clear();
    getUserMock.mockResolvedValue(null);
    findPersistedOidcUserMock.mockReturnValue(undefined);
    removeUserMock.mockResolvedValue(undefined);
    shouldStartLoginRedirectMock.mockReturnValue(true);
    shouldSuppressDevelopmentSessionRedirectMock.mockReturnValue(false);
  });

  it("injects authorization and tenant headers into requests", async () => {
    getUserMock.mockResolvedValueOnce({ access_token: "live-token" });
    window.localStorage.setItem("dev_tenant_id", "tenant-1");

    const { default: apiClient } = await import("./apiClient");
    const requestHandler =
      apiClient.interceptors.request.handlers[0]?.fulfilled;

    const result = await requestHandler?.({ headers: {} });

    expect(result.headers.Authorization).toBe("Bearer live-token");
    expect(result.headers["X-Tenant-ID"]).toBe("tenant-1");
  });

  it("rejects non-auth response errors without redirecting", async () => {
    const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
    const { default: apiClient } = await import("./apiClient");
    const responseHandler =
      apiClient.interceptors.response.handlers[0]?.rejected;
    const error = { response: { status: 500, data: { error: "boom" } } };

    await expect(responseHandler?.(error)).rejects.toBe(error);
    expect(warnSpy).not.toHaveBeenCalled();
    expect(removeUserMock).not.toHaveBeenCalled();
  });

  it("warns and rejects auth failures in test mode", async () => {
    const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
    const { default: apiClient } = await import("./apiClient");
    const responseHandler =
      apiClient.interceptors.response.handlers[0]?.rejected;
    const error = {
      response: {
        status: 403,
        data: { error: "authentication required" },
      },
    };

    await expect(responseHandler?.(error)).rejects.toBe(error);
    expect(warnSpy).toHaveBeenCalled();
    expect(removeUserMock).not.toHaveBeenCalled();
  });
});
