import { BlueprintTarget, PermissionKey, SystemRole } from "@capakraken/shared";
import { describe, expect, it, vi } from "vitest";
import { blueprintRouter } from "../router/blueprint.js";
import { clientRouter } from "../router/client.js";
import { countryRouter } from "../router/country.js";
import { managementLevelRouter } from "../router/management-level.js";
import { orgUnitRouter } from "../router/org-unit.js";
import { utilizationCategoryRouter } from "../router/utilization-category.js";
import { createCallerFactory } from "../trpc.js";

function createProtectedContext(
  db: Record<string, unknown>,
  overrides: { granted?: PermissionKey[]; denied?: PermissionKey[] } | null = null,
) {
  return {
    session: {
      user: { email: "user@example.com", name: "User", image: null },
      expires: "2099-01-01T00:00:00.000Z",
    },
    db: db as never,
    dbUser: {
      id: "user_1",
      systemRole: SystemRole.USER,
      permissionOverrides: overrides,
    },
  };
}

function createUnauthenticatedContext(db: Record<string, unknown>) {
  return {
    session: null,
    db: db as never,
    dbUser: null,
  };
}

describe("master-data router authorization", () => {
  it("requires planning read access for blueprint summaries with project counts", async () => {
    const findMany = vi.fn();
    const caller = createCallerFactory(blueprintRouter)(createProtectedContext({
      blueprint: {
        findMany,
      },
    }));

    await expect(caller.listSummaries()).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Planning read access required",
    });

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

  it("allows blueprint summaries for users with planning access", async () => {
    const findMany = vi.fn().mockResolvedValue([
      {
        id: "bp_1",
        name: "Consulting Blueprint",
        _count: { projects: 4 },
      },
    ]);
    const caller = createCallerFactory(blueprintRouter)(createProtectedContext({
      blueprint: {
        findMany,
      },
    }, {
      granted: [PermissionKey.VIEW_PLANNING],
    }));

    const result = await caller.listSummaries();

    expect(result).toHaveLength(1);
    expect(result[0]?._count.projects).toBe(4);
    expect(findMany).toHaveBeenCalledWith({
      select: {
        id: true,
        name: true,
        _count: { select: { projects: true } },
      },
      orderBy: { name: "asc" },
    });
  });

  it("requires planning read access for blueprint list and detailed reads", async () => {
    const findMany = vi.fn();
    const findUnique = vi.fn();
    const findFirst = vi.fn();
    const caller = createCallerFactory(blueprintRouter)(createProtectedContext({
      blueprint: {
        findMany,
        findUnique,
        findFirst,
      },
    }));

    await expect(caller.list({ isActive: true })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Planning read access required",
    });
    await expect(caller.getByIdentifier({ identifier: "Consulting Blueprint" })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Planning read access required",
    });
    await expect(caller.getById({ id: "bp_1" })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Planning read access required",
    });

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

  it("allows blueprint list and detailed reads for users with planning access", async () => {
    const listFindMany = vi.fn().mockResolvedValue([
      {
        id: "bp_1",
        name: "Consulting Blueprint",
        target: "PROJECT",
        description: "Default consulting setup",
        isActive: true,
      },
    ]);
    const getByIdFindUnique = vi.fn()
      .mockResolvedValueOnce({
        id: "bp_1",
        name: "Consulting Blueprint",
        target: "PROJECT",
        description: "Default consulting setup",
        fieldDefs: [{ key: "market", type: "text" }],
        defaults: { market: "EU" },
        validationRules: [],
        rolePresets: [],
        isActive: true,
      })
      .mockResolvedValueOnce(null);
    const getByIdentifierFindFirst = vi.fn().mockResolvedValue({
      id: "bp_1",
      name: "Consulting Blueprint",
      target: "PROJECT",
      description: "Default consulting setup",
      fieldDefs: [{ key: "market", type: "text" }],
      defaults: { market: "EU" },
      validationRules: [],
      rolePresets: [],
      isActive: true,
    });
    const caller = createCallerFactory(blueprintRouter)(createProtectedContext({
      blueprint: {
        findMany: listFindMany,
        findUnique: getByIdFindUnique,
        findFirst: getByIdentifierFindFirst,
      },
    }, {
      granted: [PermissionKey.VIEW_PLANNING],
    }));

    const listResult = await caller.list({ target: BlueprintTarget.PROJECT, isActive: true });
    const byIdResult = await caller.getById({ id: "bp_1" });
    const byIdentifierResult = await caller.getByIdentifier({ identifier: "Consulting Blueprint" });

    expect(listResult).toHaveLength(1);
    expect(byIdResult.name).toBe("Consulting Blueprint");
    expect(byIdentifierResult.fieldDefs).toEqual([{ key: "market", type: "text" }]);
    expect(listFindMany).toHaveBeenCalledWith({
      where: { target: "PROJECT", isActive: true },
      orderBy: { name: "asc" },
    });
    expect(getByIdFindUnique).toHaveBeenCalledWith({
      where: { id: "bp_1" },
    });
    expect(getByIdentifierFindFirst).toHaveBeenCalledWith({
      where: { name: { equals: "Consulting Blueprint", mode: "insensitive" } },
    });
  });

  it("requires authenticated planning access for global blueprint field definitions", async () => {
    const findMany = vi.fn();

    const unauthenticatedCaller = createCallerFactory(blueprintRouter)(createUnauthenticatedContext({
      blueprint: {
        findMany,
      },
    }));
    const authenticatedCaller = createCallerFactory(blueprintRouter)(createProtectedContext({
      blueprint: {
        findMany,
      },
    }));

    await expect(unauthenticatedCaller.getGlobalFieldDefs({ target: BlueprintTarget.PROJECT })).rejects.toMatchObject({
      code: "UNAUTHORIZED",
      message: "Authentication required",
    });
    await expect(authenticatedCaller.getGlobalFieldDefs({ target: BlueprintTarget.PROJECT })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Planning read access required",
    });

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

  it("allows global blueprint field definitions for users with planning access", async () => {
    const findMany = vi.fn().mockResolvedValue([
      {
        id: "bp_project_global",
        name: "Global Project Blueprint",
        fieldDefs: [
          { key: "market", label: "Market", type: "text" },
          { key: "deliveryModel", label: "Delivery Model", type: "select" },
        ],
      },
    ]);
    const caller = createCallerFactory(blueprintRouter)(createProtectedContext({
      blueprint: {
        findMany,
      },
    }, {
      granted: [PermissionKey.VIEW_PLANNING],
    }));

    const result = await caller.getGlobalFieldDefs({ target: BlueprintTarget.PROJECT });

    expect(result).toEqual([
      {
        key: "market",
        label: "Market",
        type: "text",
        blueprintId: "bp_project_global",
        blueprintName: "Global Project Blueprint",
      },
      {
        key: "deliveryModel",
        label: "Delivery Model",
        type: "select",
        blueprintId: "bp_project_global",
        blueprintName: "Global Project Blueprint",
      },
    ]);
    expect(findMany).toHaveBeenCalledWith({
      where: { target: "PROJECT", isGlobal: true, isActive: true },
      select: { id: true, name: true, fieldDefs: true },
    });
  });

  it("keeps country lists available to authenticated users as safe lookup data", async () => {
    const findMany = vi.fn().mockResolvedValue([
      {
        id: "country_de",
        code: "DE",
        name: "Germany",
        isActive: true,
        dailyWorkingHours: 8,
        metroCities: [{ id: "city_ber", name: "Berlin", countryId: "country_de" }],
      },
    ]);
    const caller = createCallerFactory(countryRouter)(createProtectedContext({
      country: {
        findMany,
      },
    }));

    const result = await caller.list({ isActive: true });

    expect(result).toHaveLength(1);
    expect(findMany).toHaveBeenCalledWith(expect.objectContaining({
      where: { isActive: true },
      include: { metroCities: { orderBy: { name: "asc" } } },
      orderBy: { name: "asc" },
    }));
  });

  it("keeps minimal country lookups available to authenticated users", async () => {
    const findFirst = vi.fn().mockResolvedValue({
      id: "country_de",
      code: "DE",
      name: "Germany",
      isActive: true,
      dailyWorkingHours: 8,
    });
    const caller = createCallerFactory(countryRouter)(createProtectedContext({
      country: {
        findUnique: vi.fn().mockResolvedValue(null),
        findFirst,
      },
    }));

    const result = await caller.resolveByIdentifier({ identifier: "de" });

    expect(result).toEqual({
      id: "country_de",
      code: "DE",
      name: "Germany",
      isActive: true,
      dailyWorkingHours: 8,
    });
    expect(findFirst).toHaveBeenCalled();
  });

  it("keeps metro-city lookups available to authenticated users", async () => {
    const findUnique = vi.fn().mockResolvedValue({
      id: "city_muc",
      name: "Munich",
      countryId: "country_de",
    });
    const caller = createCallerFactory(countryRouter)(createProtectedContext({
      metroCity: {
        findUnique,
      },
    }));

    const result = await caller.getCityById({ id: "city_muc" });

    expect(result).toEqual({
      id: "city_muc",
      name: "Munich",
      countryId: "country_de",
    });
    expect(findUnique).toHaveBeenCalledWith({
      where: { id: "city_muc" },
      select: { id: true, name: true, countryId: true },
    });
  });

  it("requires resource overview access for detailed country reads with resource counts", async () => {
    const caller = createCallerFactory(countryRouter)(createProtectedContext({
      country: {
        findFirst: vi.fn(),
        findUnique: vi.fn(),
      },
    }));

    await expect(caller.getByIdentifier({ identifier: "DE" })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Resource overview access required",
    });
    await expect(caller.getById({ id: "country_de" })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Resource overview access required",
    });
  });

  it("allows detailed country reads for users with resource overview access", async () => {
    const findFirst = vi.fn().mockResolvedValue({
      id: "country_de",
      code: "DE",
      name: "Germany",
      isActive: true,
      dailyWorkingHours: 8,
      scheduleRules: null,
      metroCities: [{ id: "city_muc", name: "Munich", countryId: "country_de" }],
      _count: { resources: 12 },
    });
    const caller = createCallerFactory(countryRouter)(createProtectedContext({
      country: {
        findUnique: vi.fn().mockResolvedValue(null),
        findFirst,
      },
    }, {
      granted: [PermissionKey.VIEW_ALL_RESOURCES],
    }));

    const result = await caller.getByIdentifier({ identifier: "DE" });

    expect(result._count.resources).toBe(12);
    expect(findFirst).toHaveBeenCalledWith(expect.objectContaining({
      include: expect.objectContaining({
        metroCities: expect.any(Object),
        _count: expect.any(Object),
      }),
    }));
  });

  it("allows detailed country reads for users with manage-resources access", async () => {
    const findUnique = vi.fn().mockResolvedValue({
      id: "country_de",
      code: "DE",
      name: "Germany",
      isActive: true,
      dailyWorkingHours: 8,
      scheduleRules: null,
      metroCities: [],
      _count: { resources: 4 },
    });
    const caller = createCallerFactory(countryRouter)(createProtectedContext({
      country: {
        findUnique,
      },
    }, {
      granted: [PermissionKey.MANAGE_RESOURCES],
    }));

    const result = await caller.getById({ id: "country_de" });

    expect(result._count.resources).toBe(4);
    expect(findUnique).toHaveBeenCalled();
  });

  it("keeps minimal org-unit lookups available to authenticated users", async () => {
    const findFirst = vi.fn()
      .mockResolvedValueOnce(null)
      .mockResolvedValueOnce({
        id: "ou_1",
        name: "Delivery",
        shortName: "DEL",
        level: 5,
        isActive: true,
      });
    const caller = createCallerFactory(orgUnitRouter)(createProtectedContext({
      orgUnit: {
        findUnique: vi.fn().mockResolvedValue(null),
        findFirst,
      },
    }));

    const result = await caller.resolveByIdentifier({ identifier: "DEL" });

    expect(result).toEqual({
      id: "ou_1",
      name: "Delivery",
      shortName: "DEL",
      level: 5,
      isActive: true,
    });
  });

  it("requires resource overview access for org-unit list and tree reads", async () => {
    const findMany = vi.fn();
    const caller = createCallerFactory(orgUnitRouter)(createProtectedContext({
      orgUnit: {
        findMany,
      },
    }));

    await expect(caller.list({ level: 5, isActive: true })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Resource overview access required",
    });
    await expect(caller.getTree({ isActive: true })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Resource overview access required",
    });

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

  it("requires resource overview access for detailed org-unit reads with staffing counts", async () => {
    const caller = createCallerFactory(orgUnitRouter)(createProtectedContext({
      orgUnit: {
        findFirst: vi.fn(),
        findUnique: vi.fn(),
      },
    }));

    await expect(caller.getByIdentifier({ identifier: "Delivery" })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Resource overview access required",
    });
    await expect(caller.getById({ id: "ou_1" })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Resource overview access required",
    });
  });

  it("allows detailed org-unit reads for users with resource overview access", async () => {
    const findFirst = vi.fn().mockResolvedValue({
      id: "ou_1",
      name: "Delivery",
      shortName: "DEL",
      level: 5,
      parentId: null,
      sortOrder: 10,
      isActive: true,
      _count: { resources: 7 },
    });
    const caller = createCallerFactory(orgUnitRouter)(createProtectedContext({
      orgUnit: {
        findUnique: vi.fn().mockResolvedValue(null),
        findFirst,
      },
    }, {
      granted: [PermissionKey.VIEW_ALL_RESOURCES],
    }));

    const result = await caller.getByIdentifier({ identifier: "Delivery" });

    expect(result._count.resources).toBe(7);
    expect(findFirst).toHaveBeenCalledWith(expect.objectContaining({
      include: { _count: { select: { resources: true } } },
    }));
  });

  it("allows org-unit list and tree reads for users with resource overview access", async () => {
    const listFindMany = vi.fn().mockResolvedValue([
      {
        id: "ou_1",
        name: "Delivery",
        shortName: "DEL",
        level: 5,
        parentId: null,
        sortOrder: 10,
        isActive: true,
        createdAt: new Date("2026-03-01T00:00:00.000Z"),
        updatedAt: new Date("2026-03-01T00:00:00.000Z"),
      },
    ]);
    const treeFindMany = vi.fn().mockResolvedValue([
      {
        id: "ou_1",
        name: "Delivery",
        shortName: "DEL",
        level: 5,
        parentId: null,
        sortOrder: 10,
        isActive: true,
        createdAt: new Date("2026-03-01T00:00:00.000Z"),
        updatedAt: new Date("2026-03-01T00:00:00.000Z"),
      },
    ]);
    const caller = createCallerFactory(orgUnitRouter)(createProtectedContext({
      orgUnit: {
        findMany: vi.fn()
          .mockImplementationOnce(listFindMany)
          .mockImplementationOnce(treeFindMany),
      },
    }, {
      granted: [PermissionKey.MANAGE_RESOURCES],
    }));

    const listResult = await caller.list({ level: 5, isActive: true });
    const treeResult = await caller.getTree({ isActive: true });

    expect(listResult).toHaveLength(1);
    expect(treeResult).toEqual([
      expect.objectContaining({
        id: "ou_1",
        name: "Delivery",
        children: [],
      }),
    ]);
    expect(listFindMany).toHaveBeenCalledWith({
      where: { level: 5, isActive: true },
      orderBy: [{ level: "asc" }, { sortOrder: "asc" }, { name: "asc" }],
    });
    expect(treeFindMany).toHaveBeenCalledWith({
      where: { isActive: true },
      orderBy: [{ sortOrder: "asc" }, { name: "asc" }],
    });
  });

  it("keeps minimal client lookups available to authenticated users", async () => {
    const findUnique = vi.fn()
      .mockResolvedValueOnce(null)
      .mockResolvedValueOnce({
        id: "client_1",
        name: "Acme Studios",
        code: "ACME",
        parentId: null,
        isActive: true,
      });
    const caller = createCallerFactory(clientRouter)(createProtectedContext({
      client: {
        findUnique,
        findFirst: vi.fn(),
      },
    }));

    const result = await caller.resolveByIdentifier({ identifier: "ACME" });

    expect(result).toEqual({
      id: "client_1",
      name: "Acme Studios",
      code: "ACME",
      parentId: null,
      isActive: true,
    });
  });

  it("requires planning read access for client list and tree reads", async () => {
    const findMany = vi.fn();
    const caller = createCallerFactory(clientRouter)(createProtectedContext({
      client: {
        findMany,
      },
    }));

    await expect(caller.list({ isActive: true })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Planning read access required",
    });
    await expect(caller.getTree({ isActive: true })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Planning read access required",
    });

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

  it("requires planning read access for detailed client reads with project counts", async () => {
    const caller = createCallerFactory(clientRouter)(createProtectedContext({
      client: {
        findFirst: vi.fn(),
        findUnique: vi.fn(),
      },
    }));

    await expect(caller.getByIdentifier({ identifier: "Acme" })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Planning read access required",
    });
    await expect(caller.getById({ id: "client_1" })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Planning read access required",
    });
  });

  it("allows client list, tree, and detail reads for users with planning access", async () => {
    const listFindMany = vi.fn().mockResolvedValue([
      {
        id: "client_1",
        name: "Acme Studios",
        code: "ACME",
        parentId: null,
        isActive: true,
        sortOrder: 10,
        tags: ["enterprise"],
        createdAt: new Date("2026-03-01T00:00:00.000Z"),
        updatedAt: new Date("2026-03-01T00:00:00.000Z"),
        _count: { children: 1, projects: 4 },
      },
    ]);
    const treeFindMany = vi.fn().mockResolvedValue([
      {
        id: "client_1",
        name: "Acme Studios",
        code: "ACME",
        parentId: null,
        isActive: true,
        sortOrder: 10,
        tags: ["enterprise"],
        createdAt: new Date("2026-03-01T00:00:00.000Z"),
        updatedAt: new Date("2026-03-01T00:00:00.000Z"),
      },
    ]);
    const getByIdFindUnique = vi.fn()
      .mockResolvedValueOnce({
        id: "client_1",
        name: "Acme Studios",
        code: "ACME",
        parentId: null,
        isActive: true,
        sortOrder: 10,
        tags: ["enterprise"],
        createdAt: new Date("2026-03-01T00:00:00.000Z"),
        updatedAt: new Date("2026-03-01T00:00:00.000Z"),
        parent: null,
        children: [],
        _count: { children: 1, projects: 4 },
      })
      .mockResolvedValueOnce(null);
    const getByIdentifierFindFirst = vi.fn().mockResolvedValue({
      id: "client_1",
      name: "Acme Studios",
      code: "ACME",
      parentId: null,
      isActive: true,
      sortOrder: 10,
      tags: ["enterprise"],
      createdAt: new Date("2026-03-01T00:00:00.000Z"),
      updatedAt: new Date("2026-03-01T00:00:00.000Z"),
      _count: { children: 1, projects: 4 },
    });
    const caller = createCallerFactory(clientRouter)(createProtectedContext({
      client: {
        findMany: vi.fn()
          .mockImplementationOnce(listFindMany)
          .mockImplementationOnce(treeFindMany),
        findUnique: getByIdFindUnique,
        findFirst: getByIdentifierFindFirst,
      },
    }, {
      granted: [PermissionKey.VIEW_PLANNING],
    }));

    const listResult = await caller.list({ isActive: true, search: "Acme" });
    const treeResult = await caller.getTree({ isActive: true });
    const byIdResult = await caller.getById({ id: "client_1" });
    const byIdentifierResult = await caller.getByIdentifier({ identifier: "Acme Studios" });

    expect(listResult).toHaveLength(1);
    expect(treeResult).toEqual([
      expect.objectContaining({
        id: "client_1",
        name: "Acme Studios",
        children: [],
      }),
    ]);
    expect(byIdResult._count.projects).toBe(4);
    expect(byIdentifierResult._count.projects).toBe(4);
    expect(listFindMany).toHaveBeenCalledWith({
      where: {
        isActive: true,
        OR: [
          { name: { contains: "Acme", mode: "insensitive" } },
          { code: { contains: "Acme", mode: "insensitive" } },
        ],
      },
      include: { _count: { select: { children: true, projects: true } } },
      orderBy: [{ sortOrder: "asc" }, { name: "asc" }],
    });
    expect(treeFindMany).toHaveBeenCalledWith({
      where: { isActive: true },
      orderBy: [{ sortOrder: "asc" }, { name: "asc" }],
    });
    expect(getByIdFindUnique).toHaveBeenCalledWith({
      where: { id: "client_1" },
      include: {
        parent: true,
        children: { orderBy: { sortOrder: "asc" } },
        _count: { select: { projects: true, children: true } },
      },
    });
    expect(getByIdentifierFindFirst).toHaveBeenCalledWith(expect.objectContaining({
      where: { name: { equals: "Acme Studios", mode: "insensitive" } },
      include: { _count: { select: { projects: true, children: true } } },
    }));
  });

  it("requires planning read access for utilization-category reads with project counts", async () => {
    const listFindMany = vi.fn();
    const getByIdFindUnique = vi.fn();
    const caller = createCallerFactory(utilizationCategoryRouter)(createProtectedContext({
      utilizationCategory: {
        findMany: listFindMany,
        findUnique: getByIdFindUnique,
      },
    }));

    await expect(caller.list({ isActive: true })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Planning read access required",
    });
    await expect(caller.getById({ id: "util_chargeable" })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Planning read access required",
    });

    expect(listFindMany).not.toHaveBeenCalled();
    expect(getByIdFindUnique).not.toHaveBeenCalled();
  });

  it("allows utilization-category reads for users with planning access", async () => {
    const listFindMany = vi.fn().mockResolvedValue([
      {
        id: "util_chargeable",
        code: "CHARGEABLE",
        name: "Chargeable",
        description: "Revenue-generating project work",
        sortOrder: 1,
        isDefault: true,
        isActive: true,
      },
    ]);
    const getByIdFindUnique = vi.fn().mockResolvedValue({
      id: "util_chargeable",
      code: "CHARGEABLE",
      name: "Chargeable",
      description: "Revenue-generating project work",
      sortOrder: 1,
      isDefault: true,
      isActive: true,
      _count: { projects: 12 },
    });
    const caller = createCallerFactory(utilizationCategoryRouter)(createProtectedContext({
      utilizationCategory: {
        findMany: listFindMany,
        findUnique: getByIdFindUnique,
      },
    }, {
      granted: [PermissionKey.VIEW_PLANNING],
    }));

    const listResult = await caller.list({ isActive: true });
    const byIdResult = await caller.getById({ id: "util_chargeable" });

    expect(listResult).toHaveLength(1);
    expect(byIdResult._count.projects).toBe(12);
    expect(listFindMany).toHaveBeenCalledWith({
      where: { isActive: true },
      orderBy: { sortOrder: "asc" },
    });
    expect(getByIdFindUnique).toHaveBeenCalledWith({
      where: { id: "util_chargeable" },
      include: { _count: { select: { projects: true } } },
    });
  });

  it("requires planning read access for management-level reads", async () => {
    const listFindMany = vi.fn();
    const getByIdFindUnique = vi.fn();
    const caller = createCallerFactory(managementLevelRouter)(createProtectedContext({
      managementLevelGroup: {
        findMany: listFindMany,
        findUnique: getByIdFindUnique,
      },
    }));

    await expect(caller.listGroups()).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Planning read access required",
    });
    await expect(caller.getGroupById({ id: "mgmt_group_1" })).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "Planning read access required",
    });

    expect(listFindMany).not.toHaveBeenCalled();
    expect(getByIdFindUnique).not.toHaveBeenCalled();
  });

  it("allows management-level reads for users with planning access", async () => {
    const listFindMany = vi.fn().mockResolvedValue([
      {
        id: "mgmt_group_1",
        name: "Team Leads",
        targetPercentage: 0.72,
        sortOrder: 10,
        levels: [{ id: "mgmt_level_1", name: "Senior Team Lead" }],
      },
    ]);
    const getByIdFindUnique = vi.fn().mockResolvedValue({
      id: "mgmt_group_1",
      name: "Team Leads",
      targetPercentage: 0.72,
      sortOrder: 10,
      levels: [{ id: "mgmt_level_1", name: "Senior Team Lead" }],
      _count: { resources: 6 },
    });
    const caller = createCallerFactory(managementLevelRouter)(createProtectedContext({
      managementLevelGroup: {
        findMany: listFindMany,
        findUnique: getByIdFindUnique,
      },
    }, {
      granted: [PermissionKey.VIEW_PLANNING],
    }));

    const listResult = await caller.listGroups();
    const detailResult = await caller.getGroupById({ id: "mgmt_group_1" });

    expect(listResult).toHaveLength(1);
    expect(detailResult._count.resources).toBe(6);
    expect(listFindMany).toHaveBeenCalledWith({
      include: { levels: { orderBy: { name: "asc" } } },
      orderBy: { sortOrder: "asc" },
    });
    expect(getByIdFindUnique).toHaveBeenCalledWith({
      where: { id: "mgmt_group_1" },
      include: {
        levels: { orderBy: { name: "asc" } },
        _count: { select: { resources: true } },
      },
    });
  });
});
