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

const { mockCheckPermissions } = vi.hoisted(() => ({
  mockCheckPermissions: vi.fn(),
}));

vi.mock("$lib", () => ({
  optima: {
    user: {
      checkPermissions: mockCheckPermissions,
    },
  },
}));

import {
  checkPermissions,
  hasPermission,
  resolvePermissions,
} from "./permissions";

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

  it("returns empty map when no permissions are requested", async () => {
    const result = await checkPermissions("token", []);

    expect(result).toEqual({});
    expect(mockCheckPermissions).not.toHaveBeenCalled();
  });

  it("maps API response into permission booleans", async () => {
    mockCheckPermissions.mockResolvedValueOnce({
      data: {
        results: [
          { permission: "company.read", hasPermission: true },
          { permission: "credential.create", hasPermission: false },
        ],
      },
    });

    const result = await checkPermissions("token", [
      "company.read",
      "credential.create",
    ]);

    expect(result).toEqual({
      "company.read": true,
      "credential.create": false,
    });
  });

  it("defaults requested permissions to true on API error and marks __checkFailed", async () => {
    mockCheckPermissions.mockRejectedValueOnce(new Error("request failed"));

    const result = await checkPermissions("token", ["a", "b"]);

    expect(result.a).toBe(true);
    expect(result.b).toBe(true);
    expect(result.__checkFailed).toBe(true);
  });

  it("returns all-true with __checkFailed when accessToken is empty", async () => {
    const result = await checkPermissions("", ["x", "y"]);

    expect(result.x).toBe(true);
    expect(result.y).toBe(true);
    expect(result.__checkFailed).toBe(true);
    expect(mockCheckPermissions).not.toHaveBeenCalled();
  });

  it("returns all-true with __checkFailed when accessToken is falsy", async () => {
    const result = await checkPermissions(undefined as unknown as string, [
      "perm.a",
    ]);

    expect(result["perm.a"]).toBe(true);
    expect(result.__checkFailed).toBe(true);
    expect(mockCheckPermissions).not.toHaveBeenCalled();
  });

  it("hasPermission returns true only for explicit true values", () => {
    expect(hasPermission({ "company.read": true }, "company.read")).toBe(true);
    expect(hasPermission({ "company.read": false }, "company.read")).toBe(
      false,
    );
    expect(hasPermission({}, "company.read")).toBe(false);
  });

  it("exports resolvePermissions as backward-compatible alias", () => {
    expect(resolvePermissions).toBe(checkPermissions);
  });
});
