import { TRPCError } from "@trpc/server";
import { PermissionKey, SystemRole } from "@capakraken/shared";
import { describe, expect, it, vi } from "vitest";
import {
  assertCanReadResource,
  canReadAllResources,
  findOwnedResourceId,
  resolveResourcePermissions,
} from "../lib/resource-access.js";

describe("resource access helpers", () => {
  it("returns no permissions without a db user", () => {
    expect(resolveResourcePermissions({ dbUser: null, roleDefaults: null })).toEqual(new Set());
  });

  it("treats managers with resource permissions as staff readers", () => {
    const permissions = resolveResourcePermissions({
      dbUser: {
        systemRole: SystemRole.MANAGER,
        permissionOverrides: null,
      } as never,
      roleDefaults: null,
    });

    expect(permissions.has(PermissionKey.VIEW_ALL_RESOURCES)).toBe(true);
    expect(canReadAllResources({
      dbUser: {
        systemRole: SystemRole.MANAGER,
        permissionOverrides: null,
      } as never,
      roleDefaults: null,
    })).toBe(true);
  });

  it("returns null when no linked resource lookup is possible", async () => {
    await expect(findOwnedResourceId({
      dbUser: { id: "user_1" } as never,
      roleDefaults: null,
      db: {},
    })).resolves.toBeNull();
  });

  it("returns the owned resource id when the lookup succeeds", async () => {
    const findFirst = vi.fn().mockResolvedValue({ id: "res_1" });

    await expect(findOwnedResourceId({
      dbUser: { id: "user_1" } as never,
      roleDefaults: null,
      db: {
        resource: {
          findFirst,
        },
      } as never,
    })).resolves.toBe("res_1");

    expect(findFirst).toHaveBeenCalledWith({
      where: { userId: "user_1" },
      select: { id: true },
    });
  });

  it("allows staff readers to access arbitrary resources without ownership lookup", async () => {
    const findFirst = vi.fn();

    await expect(assertCanReadResource({
      dbUser: {
        id: "mgr_1",
        systemRole: SystemRole.MANAGER,
        permissionOverrides: null,
      } as never,
      roleDefaults: null,
      db: {
        resource: {
          findFirst,
        },
      } as never,
    }, "res_1")).resolves.toBeUndefined();

    expect(findFirst).not.toHaveBeenCalled();
  });

  it("rejects non-owned resources for regular users", async () => {
    const findFirst = vi.fn().mockResolvedValue({ id: "res_own" });

    await expect(assertCanReadResource({
      dbUser: {
        id: "user_1",
        systemRole: SystemRole.USER,
        permissionOverrides: null,
      } as never,
      roleDefaults: null,
      db: {
        resource: {
          findFirst,
        },
      } as never,
    }, "res_other", "custom message")).rejects.toEqual(expect.objectContaining<Partial<TRPCError>>({
      code: "FORBIDDEN",
      message: "custom message",
    }));
  });
});
