import { SystemRole } from "@capakraken/shared";
import { describe, expect, it, vi } from "vitest";
import { managementLevelRouter } from "../router/management-level.js";
import { createCallerFactory } from "../trpc.js";

const createCaller = createCallerFactory(managementLevelRouter);

function createPlanningCaller(db: Record<string, unknown>) {
  return createCaller({
    session: {
      user: { email: "planning@example.com", name: "Planning", image: null },
      expires: "2099-01-01T00:00:00.000Z",
    },
    db: db as never,
    dbUser: {
      id: "user_planning",
      systemRole: SystemRole.MANAGER,
      permissionOverrides: null,
    },
    permissions: new Set(["view:planning"]),
  });
}

function createAdminCaller(db: Record<string, unknown>) {
  return createCaller({
    session: {
      user: { email: "admin@example.com", name: "Admin", image: null },
      expires: "2099-01-01T00:00:00.000Z",
    },
    db: db as never,
    dbUser: {
      id: "user_admin",
      systemRole: SystemRole.ADMIN,
      permissionOverrides: null,
    },
  });
}

describe("managementLevel router", () => {
  it("lists groups ordered by sort order", async () => {
    const findMany = vi.fn().mockResolvedValue([
      { id: "grp_1", name: "Seniority", sortOrder: 1, levels: [] },
    ]);

    const caller = createPlanningCaller({
      managementLevelGroup: { findMany },
    });
    const result = await caller.listGroups();

    expect(findMany).toHaveBeenCalledWith({
      include: { levels: { orderBy: { name: "asc" } } },
      orderBy: { sortOrder: "asc" },
    });
    expect(result).toHaveLength(1);
  });

  it("creates a group through the router", async () => {
    const create = vi.fn().mockResolvedValue({
      id: "grp_1",
      name: "Seniority",
      targetPercentage: 0.2,
      sortOrder: 1,
      levels: [],
    });

    const caller = createAdminCaller({
      managementLevelGroup: {
        findUnique: vi.fn().mockResolvedValue(null),
        create,
      },
    });
    const result = await caller.createGroup({
      name: "Seniority",
      targetPercentage: 0.2,
      sortOrder: 1,
    });

    expect(create).toHaveBeenCalledWith(expect.objectContaining({
      data: {
        name: "Seniority",
        targetPercentage: 0.2,
        sortOrder: 1,
      },
      include: { levels: true },
    }));
    expect(result.id).toBe("grp_1");
  });

  it("updates a group and preserves auditable before/after state", async () => {
    const update = vi.fn().mockResolvedValue({
      id: "grp_1",
      name: "Leadership",
      targetPercentage: 0.3,
      sortOrder: 2,
      levels: [],
    });

    const caller = createAdminCaller({
      managementLevelGroup: {
        findUnique: vi
          .fn()
          .mockResolvedValueOnce({ id: "grp_1", name: "Seniority", targetPercentage: 0.2, sortOrder: 1 })
          .mockResolvedValueOnce(null),
        update,
      },
    });
    const result = await caller.updateGroup({
      id: "grp_1",
      data: { name: "Leadership", targetPercentage: 0.3, sortOrder: 2 },
    });

    expect(update).toHaveBeenCalledWith({
      where: { id: "grp_1" },
      data: { name: "Leadership", targetPercentage: 0.3, sortOrder: 2 },
      include: { levels: true },
    });
    expect(result.name).toBe("Leadership");
  });

  it("creates and updates a level through the router", async () => {
    const create = vi.fn().mockResolvedValue({
      id: "lvl_1",
      name: "Principal",
      groupId: "grp_1",
    });
    const update = vi.fn().mockResolvedValue({
      id: "lvl_1",
      name: "Lead",
      groupId: "grp_1",
    });

    const caller = createAdminCaller({
      managementLevelGroup: {
        findUnique: vi.fn().mockResolvedValue({ id: "grp_1", name: "Seniority" }),
      },
      managementLevel: {
        findUnique: vi
          .fn()
          .mockResolvedValueOnce(null)
          .mockResolvedValueOnce({ id: "lvl_1", name: "Principal", groupId: "grp_1" })
          .mockResolvedValueOnce(null),
        create,
        update,
      },
    });

    const created = await caller.createLevel({ name: "Principal", groupId: "grp_1" });
    const updated = await caller.updateLevel({ id: "lvl_1", data: { name: "Lead" } });

    expect(create).toHaveBeenCalledWith({
      data: { name: "Principal", groupId: "grp_1" },
    });
    expect(update).toHaveBeenCalledWith({
      where: { id: "lvl_1" },
      data: { name: "Lead" },
    });
    expect(created.id).toBe("lvl_1");
    expect(updated.name).toBe("Lead");
  });

  it("deletes a deletable level and returns success", async () => {
    const deleteFn = vi.fn().mockResolvedValue({});

    const caller = createAdminCaller({
      managementLevel: {
        findUnique: vi.fn().mockResolvedValue({
          id: "lvl_1",
          name: "Lead",
          _count: { resources: 0 },
        }),
        delete: deleteFn,
      },
    });

    const result = await caller.deleteLevel({ id: "lvl_1" });

    expect(deleteFn).toHaveBeenCalledWith({ where: { id: "lvl_1" } });
    expect(result).toEqual({ success: true });
  });
});
