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

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

vi.mock("../lib/audit.js", () => ({
  createAuditEntry,
}));

import {
  createOrgUnit,
  deactivateOrgUnit,
  updateOrgUnit,
} from "../router/org-unit-procedure-support.js";

function createContext(db: Record<string, unknown>) {
  return {
    db: db as never,
    dbUser: { id: "user_admin" } as never,
  };
}

describe("org-unit procedure support", () => {
  beforeEach(() => {
    createAuditEntry.mockReset();
  });

  it("creates an org unit after validating the parent level", async () => {
    const findUnique = vi.fn().mockResolvedValue({
      id: "ou_parent",
      level: 5,
      name: "Delivery",
    });
    const create = vi.fn().mockResolvedValue({
      id: "ou_child",
      name: "Delivery Germany",
      level: 6,
      parentId: "ou_parent",
      sortOrder: 20,
    });

    const result = await createOrgUnit(
      createContext({
        orgUnit: { findUnique, create },
      }),
      {
        name: "Delivery Germany",
        level: 6,
        parentId: "ou_parent",
        sortOrder: 20,
      },
    );

    expect(findUnique).toHaveBeenCalledWith({
      where: { id: "ou_parent" },
    });
    expect(create).toHaveBeenCalledWith({
      data: {
        name: "Delivery Germany",
        level: 6,
        parentId: "ou_parent",
        sortOrder: 20,
      },
    });
    expect(result.id).toBe("ou_child");
    expect(createAuditEntry).toHaveBeenCalledWith(
      expect.objectContaining({
        entityType: "OrgUnit",
        action: "CREATE",
        entityId: "ou_child",
      }),
    );
  });

  it("updates an org unit and preserves the before snapshot", async () => {
    const findUnique = vi.fn().mockResolvedValue({
      id: "ou_child",
      name: "Delivery Germany",
      shortName: "DE",
      isActive: true,
    });
    const update = vi.fn().mockResolvedValue({
      id: "ou_child",
      name: "Delivery Europe",
      shortName: "EU",
      isActive: true,
    });

    const result = await updateOrgUnit(
      createContext({
        orgUnit: { findUnique, update },
      }),
      {
        id: "ou_child",
        data: {
          name: "Delivery Europe",
          shortName: "EU",
        },
      },
    );

    expect(update).toHaveBeenCalledWith({
      where: { id: "ou_child" },
      data: {
        name: "Delivery Europe",
        shortName: "EU",
      },
    });
    expect(result.name).toBe("Delivery Europe");
    expect(createAuditEntry).toHaveBeenCalledWith(
      expect.objectContaining({
        entityType: "OrgUnit",
        action: "UPDATE",
        before: expect.objectContaining({ name: "Delivery Germany" }),
        after: expect.objectContaining({ name: "Delivery Europe" }),
      }),
    );
  });

  it("deactivates an org unit with the dedicated audit summary", async () => {
    const update = vi.fn().mockResolvedValue({
      id: "ou_child",
      name: "Delivery Europe",
      isActive: false,
    });

    const result = await deactivateOrgUnit(
      createContext({
        orgUnit: { update },
      }),
      { id: "ou_child" },
    );

    expect(update).toHaveBeenCalledWith({
      where: { id: "ou_child" },
      data: { isActive: false },
    });
    expect(result.isActive).toBe(false);
    expect(createAuditEntry).toHaveBeenCalledWith(
      expect.objectContaining({
        entityType: "OrgUnit",
        summary: "Deactivated OrgUnit",
        before: { isActive: true },
        after: { isActive: false },
      }),
    );
  });
});
