// @vitest-environment jsdom
import { beforeEach, describe, expect, it, vi } from "vitest";

const fetchMock = vi.fn();
vi.stubGlobal("fetch", fetchMock);

vi.mock("@/stores/connection-store", () => ({
  useConnectionStore: {
    subscribe: () => () => {},
  },
}));

vi.mock("@/lib/api", () => ({
  formatHeaders: () => new Headers(),
}));

describe("useAuth anonymous happy path", () => {
  beforeEach(() => {
    fetchMock.mockReset();
    vi.resetModules();
  });

  it("sets role to admin when authEnabled is false", async () => {
    fetchMock.mockResolvedValueOnce({
      ok: true,
      json: async () => ({ authEnabled: false }),
    });

    const { renderHook, act } = await import("@testing-library/react");
    const { useAuth } = await import("@/hooks/use-auth");

    const { result } = renderHook(() => useAuth());

    await act(async () => {});

    expect(result.current.loading).toBe(false);
    expect(result.current.authEnabled).toBe(false);
    expect(result.current.isAuthenticated).toBe(true);
    expect(result.current.role).toBe("admin");
  });

  it("includes settings:write in anonymous permissions", async () => {
    fetchMock.mockResolvedValueOnce({
      ok: true,
      json: async () => ({ authEnabled: false }),
    });

    const { renderHook, act } = await import("@testing-library/react");
    const { useAuth } = await import("@/hooks/use-auth");

    const { result } = renderHook(() => useAuth());

    await act(async () => {});

    expect(result.current.hasPermission("settings:write")).toBe(true);
    expect(result.current.hasPermission("settings:read")).toBe(true);
  });

  it("includes all admin permissions in anonymous mode", async () => {
    fetchMock.mockResolvedValueOnce({
      ok: true,
      json: async () => ({ authEnabled: false }),
    });

    const { renderHook, act } = await import("@testing-library/react");
    const { useAuth } = await import("@/hooks/use-auth");

    const { result } = renderHook(() => useAuth());

    await act(async () => {});

    const expectedPerms = [
      "tools:use",
      "files:own",
      "files:all",
      "apikeys:own",
      "apikeys:all",
      "pipelines:own",
      "pipelines:all",
      "settings:read",
      "settings:write",
      "users:manage",
      "teams:manage",
      "features:manage",
      "system:health",
      "audit:read",
    ];
    for (const perm of expectedPerms) {
      expect(result.current.hasPermission(perm)).toBe(true);
    }
  });

  it("does not call session endpoint when auth is disabled", async () => {
    fetchMock.mockResolvedValueOnce({
      ok: true,
      json: async () => ({ authEnabled: false }),
    });

    const { renderHook, act } = await import("@testing-library/react");
    const { useAuth } = await import("@/hooks/use-auth");

    renderHook(() => useAuth());

    await act(async () => {});

    expect(fetchMock).toHaveBeenCalledTimes(1);
    expect(fetchMock.mock.calls[0][0]).toBe("/api/v1/config/auth");
  });

  it("does NOT grant admin when authEnabled is true and session fails", async () => {
    fetchMock
      .mockResolvedValueOnce({
        ok: true,
        json: async () => ({ authEnabled: true }),
      })
      .mockResolvedValueOnce({
        ok: false,
        json: async () => ({}),
      });

    const { renderHook, act } = await import("@testing-library/react");
    const { useAuth } = await import("@/hooks/use-auth");

    const { result } = renderHook(() => useAuth());

    await act(async () => {});

    expect(result.current.isAuthenticated).toBe(false);
    expect(result.current.role).toBeNull();
    expect(result.current.permissions).toEqual([]);
  });
});

describe("useAuth hasPermission", () => {
  beforeEach(() => {
    fetchMock.mockReset();
    vi.resetModules();
  });

  it("returns false for permissions not in the list", async () => {
    fetchMock.mockResolvedValueOnce({
      ok: true,
      json: async () => ({ authEnabled: false }),
    });

    const { renderHook, act } = await import("@testing-library/react");
    const { useAuth } = await import("@/hooks/use-auth");

    const { result } = renderHook(() => useAuth());

    await act(async () => {});

    expect(result.current.hasPermission("nonexistent:permission")).toBe(false);
  });
});
