import { PermissionKey, SystemRole } from "@capakraken/shared";
import { describe, expect, it, vi } from "vitest";
import { importExportRouter } from "../router/import-export.js";
import { createCallerFactory } from "../trpc.js";

const createCaller = createCallerFactory(importExportRouter);

function createProtectedCaller(
  db: Record<string, unknown>,
  options: {
    role?: SystemRole;
    granted?: PermissionKey[];
    denied?: PermissionKey[];
  } = {},
) {
  const { role = SystemRole.USER, granted = [], denied = [] } = options;
  const hasOverrides = granted.length > 0 || denied.length > 0;

  return createCaller({
    session: {
      user: { email: "user@example.com", name: "User", image: null },
      expires: "2099-01-01T00:00:00.000Z",
    },
    db: db as never,
    dbUser: {
      id: role === SystemRole.ADMIN ? "user_admin" : "user_1",
      systemRole: role,
      permissionOverrides: hasOverrides ? { ...(granted.length > 0 ? { granted } : {}), ...(denied.length > 0 ? { denied } : {}) } : null,
    },
    roleDefaults: null,
  });
}

describe("import-export router", () => {
  it("exports resources for controller callers", async () => {
    const caller = createProtectedCaller(
      {
        resource: {
          findMany: vi.fn().mockResolvedValue([
            {
              eid: "E-001",
              displayName: "Ada Lovelace",
              email: "ada@example.com",
              chapter: "Consulting",
              lcrCents: 10000,
              ucrCents: 20000,
              currency: "EUR",
              chargeabilityTarget: 0.8,
              dynamicFields: {},
            },
          ]),
        },
        blueprint: {
          findMany: vi.fn().mockResolvedValue([]),
        },
      },
      { role: SystemRole.CONTROLLER },
    );

    const csv = await caller.exportResourcesCSV();

    expect(csv).toContain("eid,displayName,email,chapter");
    expect(csv).toContain("E-001,Ada Lovelace");
  });

  it("allows managers with import permission to import CSV rows", async () => {
    const resourceFindFirst = vi.fn().mockResolvedValue({
      id: "res_1",
      displayName: "Ada",
      email: "ada-old@example.com",
      chapter: "Old",
      lcrCents: 9000,
    });
    const resourceUpdate = vi.fn().mockResolvedValue({ id: "res_1" });
    const auditCreate = vi.fn().mockResolvedValue({ id: "audit_1" });

    const caller = createProtectedCaller(
      {
        resource: {
          findFirst: resourceFindFirst,
          update: resourceUpdate,
        },
        auditLog: {
          create: auditCreate,
        },
      },
      {
        role: SystemRole.MANAGER,
        granted: [PermissionKey.IMPORT_DATA],
      },
    );

    const result = await caller.importCSV({
      entityType: "resources",
      rows: [{ eid: "E-001", displayName: "Ada Lovelace" }],
      dryRun: false,
    });

    expect(resourceUpdate).toHaveBeenCalledWith({
      where: { id: "res_1" },
      data: {
        displayName: "Ada Lovelace",
        email: "ada-old@example.com",
        chapter: "Old",
        lcrCents: 9000,
      },
    });
    expect(result.updated).toBe(1);
  });

  it("blocks managers without the import permission", async () => {
    const caller = createProtectedCaller(
      {
        resource: {
          findFirst: vi.fn(),
          update: vi.fn(),
        },
        auditLog: {
          create: vi.fn(),
        },
      },
      {
        role: SystemRole.MANAGER,
        denied: [PermissionKey.IMPORT_DATA],
      },
    );

    await expect(
      caller.importCSV({
        entityType: "resources",
        rows: [],
        dryRun: true,
      }),
    ).rejects.toThrow(PermissionKey.IMPORT_DATA);
  });
});
