import { AllocationStatus } from "@capakraken/shared";
import { describe, expect, it, vi } from "vitest";
import {
  createAssignment,
  createDemandRequirement,
  fillDemandRequirement,
  fillOpenDemand,
} from "../index.js";

describe("demand and assignment use-cases", () => {
  it("creates a demand requirement and writes an audit event", async () => {
    const projectFindUnique = vi.fn().mockResolvedValue({ id: "project_1" });
    const demandRequirementCreate = vi.fn().mockResolvedValue({
      id: "demand_1",

      projectId: "project_1",
      startDate: new Date("2026-03-16"),
      endDate: new Date("2026-03-27"),
      hoursPerDay: 4,
      percentage: 50,
      role: "Compositor",
      roleId: "role_comp",
      headcount: 2,
      status: AllocationStatus.PROPOSED,
      metadata: { estimateHandoff: { estimateId: "est_1" } },
      createdAt: new Date("2026-03-13"),
      updatedAt: new Date("2026-03-13"),
      project: { id: "project_1", name: "Project One", shortCode: "PRJ" },
      roleEntity: { id: "role_comp", name: "Compositor", color: "#111111" },
    });
    const auditLogCreate = vi.fn().mockResolvedValue({});

    const result = await createDemandRequirement(
      {
        project: { findUnique: projectFindUnique },
        demandRequirement: { create: demandRequirementCreate },
        auditLog: { create: auditLogCreate },
      } as never,
      {
        projectId: "project_1",
        startDate: new Date("2026-03-16"),
        endDate: new Date("2026-03-27"),
        hoursPerDay: 4,
        percentage: 50,
        role: "Compositor",
        roleId: "role_comp",
        headcount: 2,
        status: AllocationStatus.PROPOSED,
        metadata: { estimateHandoff: { estimateId: "est_1" } },
      },
    );

    expect(result.id).toBe("demand_1");
    expect(demandRequirementCreate).toHaveBeenCalledWith(
      expect.objectContaining({
        data: expect.objectContaining({
          projectId: "project_1",
          headcount: 2,
          roleId: "role_comp",
        }),
      }),
    );
    expect(auditLogCreate).toHaveBeenCalledWith(
      expect.objectContaining({
        data: expect.objectContaining({
          entityType: "DemandRequirement",
          entityId: "demand_1",
        }),
      }),
    );
  });

  it("creates an assignment linked to a demand requirement", async () => {
    const projectFindUnique = vi.fn().mockResolvedValue({ id: "project_1" });
    const resourceFindUnique = vi.fn().mockResolvedValue({
      id: "resource_1",
      lcrCents: 5000,
      availability: {
        monday: 8,
        tuesday: 8,
        wednesday: 8,
        thursday: 8,
        friday: 8,
        saturday: 0,
        sunday: 0,
      },
    });
    const demandRequirementFindUnique = vi.fn().mockResolvedValue({
      id: "demand_1",
      projectId: "project_1",
    });
    const assignmentFindMany = vi.fn().mockResolvedValue([]);
    const allocationFindMany = vi.fn().mockResolvedValue([]);
    const vacationFindMany = vi.fn().mockResolvedValue([]);
    const assignmentCreate = vi.fn().mockResolvedValue({
      id: "assignment_1",

      demandRequirementId: "demand_1",
      resourceId: "resource_1",
      projectId: "project_1",
      startDate: new Date("2026-03-16"),
      endDate: new Date("2026-03-27"),
      hoursPerDay: 4,
      percentage: 50,
      role: "Compositor",
      roleId: "role_comp",
      dailyCostCents: 20000,
      status: AllocationStatus.PROPOSED,
      metadata: {},
      createdAt: new Date("2026-03-13"),
      updatedAt: new Date("2026-03-13"),
      resource: { id: "resource_1", displayName: "Alice", eid: "E-001", lcrCents: 5000 },
      project: { id: "project_1", name: "Project One", shortCode: "PRJ" },
      roleEntity: { id: "role_comp", name: "Compositor", color: "#111111" },
      demandRequirement: {
        id: "demand_1",
        projectId: "project_1",
        startDate: new Date("2026-03-16"),
        endDate: new Date("2026-03-27"),
        hoursPerDay: 4,
        percentage: 50,
        role: "Compositor",
        roleId: "role_comp",
        headcount: 1,
        status: AllocationStatus.PROPOSED,
      },
    });
    const auditLogCreate = vi.fn().mockResolvedValue({});

    const result = await createAssignment(
      {
        project: { findUnique: projectFindUnique },
        resource: { findUnique: resourceFindUnique },
        demandRequirement: { findUnique: demandRequirementFindUnique },
        assignment: { findMany: assignmentFindMany, create: assignmentCreate },
        allocation: { findMany: allocationFindMany },
        vacation: { findMany: vacationFindMany },
        auditLog: { create: auditLogCreate },
      } as never,
      {
        demandRequirementId: "demand_1",
        resourceId: "resource_1",
        projectId: "project_1",
        startDate: new Date("2026-03-16"),
        endDate: new Date("2026-03-27"),
        hoursPerDay: 4,
        percentage: 50,
        role: "Compositor",
        roleId: "role_comp",
        status: AllocationStatus.PROPOSED,
        metadata: {},
      },
    );

    expect(result.id).toBe("assignment_1");
    expect(assignmentCreate).toHaveBeenCalledWith(
      expect.objectContaining({
        data: expect.objectContaining({
          demandRequirementId: "demand_1",
          resourceId: "resource_1",
          dailyCostCents: expect.any(Number),
        }),
      }),
    );
    expect(auditLogCreate).toHaveBeenCalledWith(
      expect.objectContaining({
        data: expect.objectContaining({
          entityType: "Assignment",
          entityId: "assignment_1",
        }),
      }),
    );
  });


  it("fills one seat of a multi-headcount demand requirement", async () => {
    const initialDemandRequirement = {
      id: "demand_1",
      projectId: "project_1",
      startDate: new Date("2026-03-16"),
      endDate: new Date("2026-03-27"),
      hoursPerDay: 4,
      percentage: 50,
      role: "FX Artist",
      roleId: "role_fx",
      headcount: 2,
      status: AllocationStatus.PROPOSED,
      metadata: {},
    };
    const updatedDemandRequirement = {
      id: "demand_1",
      projectId: "project_1",
      headcount: 1,
      status: AllocationStatus.PROPOSED,
    };
    const demandIdReads = [initialDemandRequirement, updatedDemandRequirement];
    const demandRequirementFindUnique = vi.fn().mockImplementation(({ where }) => {
      if (where.id === "demand_1") {
        return Promise.resolve(demandIdReads.shift() ?? null);
      }

      return Promise.resolve(null);
    });
    const resourceFindUnique = vi.fn().mockResolvedValue({
      id: "resource_1",
      lcrCents: 6000,
      availability: {
        monday: 8,
        tuesday: 8,
        wednesday: 8,
        thursday: 8,
        friday: 8,
        saturday: 0,
        sunday: 0,
      },
    });
    const txDemandRequirementFindUnique = vi.fn().mockResolvedValue({
      id: "demand_1",
      projectId: "project_1",
    });
    const projectFindUnique = vi.fn().mockResolvedValue({ id: "project_1" });
    const assignmentFindMany = vi.fn().mockResolvedValue([]);
    const allocationFindMany = vi.fn().mockResolvedValue([]);
    const vacationFindMany = vi.fn().mockResolvedValue([]);
    const assignmentCreate = vi.fn().mockResolvedValue({
      id: "assignment_1",

      demandRequirementId: "demand_1",
      resourceId: "resource_1",
      projectId: "project_1",
      startDate: new Date("2026-03-16"),
      endDate: new Date("2026-03-27"),
      hoursPerDay: 4,
      percentage: 50,
      role: "FX Artist",
      roleId: "role_fx",
      dailyCostCents: 24000,
      status: AllocationStatus.PROPOSED,
      metadata: {},
      createdAt: new Date("2026-03-13"),
      updatedAt: new Date("2026-03-13"),
      resource: { id: "resource_1", displayName: "Bob", eid: "E-002", lcrCents: 6000 },
      project: { id: "project_1", name: "Project One", shortCode: "PRJ" },
      roleEntity: { id: "role_fx", name: "FX Artist", color: "#222222" },
      demandRequirement: {
        id: "demand_1",
        projectId: "project_1",
        startDate: new Date("2026-03-16"),
        endDate: new Date("2026-03-27"),
        hoursPerDay: 4,
        percentage: 50,
        role: "FX Artist",
        roleId: "role_fx",
        headcount: 2,
        status: AllocationStatus.PROPOSED,
      },
    });
    const demandRequirementUpdate = vi.fn().mockResolvedValue({
      id: "demand_1",
      projectId: "project_1",
      headcount: 1,
      status: AllocationStatus.PROPOSED,

    });
    const assignmentUpdate = vi.fn();
    const allocationCreate = vi.fn();
    const allocationUpdate = vi.fn();
    const allocationDelete = vi.fn().mockResolvedValue({});
    const auditLogCreate = vi.fn().mockResolvedValue({});

    const db = {
      demandRequirement: { findUnique: demandRequirementFindUnique },
      assignment: { findMany: assignmentFindMany },
      resource: { findUnique: resourceFindUnique },
      $transaction: vi.fn(async (callback) =>
        callback({
          project: { findUnique: projectFindUnique },
          resource: { findUnique: resourceFindUnique },
          demandRequirement: {
            findUnique: txDemandRequirementFindUnique,
            update: demandRequirementUpdate,
          },
          assignment: {
            findMany: assignmentFindMany,
            create: assignmentCreate,
            update: assignmentUpdate,
          },
          vacation: { findMany: vacationFindMany },
          auditLog: { create: auditLogCreate },
        }),
      ),
    };

    const result = await fillDemandRequirement(db as never, {
      demandRequirementId: "demand_1",
      resourceId: "resource_1",
    });

    expect(result.assignment.id).toBe("assignment_1");
    expect(result.updatedDemandRequirement).toMatchObject({
      id: "demand_1",
      headcount: 1,
      status: AllocationStatus.PROPOSED,

    });
    expect(demandRequirementUpdate).toHaveBeenCalledWith(
      expect.objectContaining({
        where: { id: "demand_1" },
        data: { headcount: 1 },
      }),
    );
    expect(assignmentUpdate).not.toHaveBeenCalled();
  });

  it("fills a single-seat legacy-backed demand requirement by completing it in place", async () => {
    const initialDemandRequirement = {
      id: "demand_2",
      projectId: "project_1",
      startDate: new Date("2026-04-01"),
      endDate: new Date("2026-04-11"),
      hoursPerDay: 6,
      percentage: 75,
      role: "Lead",
      roleId: "role_lead",
      headcount: 1,
      status: AllocationStatus.PROPOSED,
      metadata: {},
    };
    const updatedDemandRequirement = {
      id: "demand_2",
      projectId: "project_1",
      headcount: 1,
      status: AllocationStatus.COMPLETED,
    };
    const demandIdReads = [initialDemandRequirement, updatedDemandRequirement];
    const demandRequirementFindUnique = vi.fn().mockImplementation(({ where }) => {
      if (where.id === "demand_2") {
        return Promise.resolve(demandIdReads.shift() ?? null);
      }

      return Promise.resolve(null);
    });
    const resourceFindUnique = vi.fn().mockResolvedValue({
      id: "resource_2",
      lcrCents: 7000,
      availability: {
        monday: 8,
        tuesday: 8,
        wednesday: 8,
        thursday: 8,
        friday: 8,
        saturday: 0,
        sunday: 0,
      },
    });
    const projectFindUnique = vi.fn().mockResolvedValue({ id: "project_1" });
    const txDemandRequirementFindUnique = vi.fn().mockResolvedValue({
      id: "demand_2",
      projectId: "project_1",
    });
    const assignmentFindMany = vi.fn().mockResolvedValue([]);
    const allocationFindMany = vi.fn().mockResolvedValue([]);
    const vacationFindMany = vi.fn().mockResolvedValue([]);
    const assignmentCreate = vi.fn().mockResolvedValue({
      id: "assignment_2",
      demandRequirementId: "demand_2",
      resourceId: "resource_2",
      projectId: "project_1",
      startDate: new Date("2026-04-01"),
      endDate: new Date("2026-04-11"),
      hoursPerDay: 6,
      percentage: 75,
      role: "Lead",
      roleId: "role_lead",
      dailyCostCents: 42000,
      status: AllocationStatus.PROPOSED,
      metadata: {},
      createdAt: new Date("2026-03-13"),
      updatedAt: new Date("2026-03-13"),
      resource: { id: "resource_2", displayName: "Carol", eid: "E-003", lcrCents: 7000 },
      project: { id: "project_1", name: "Project One", shortCode: "PRJ" },
      roleEntity: { id: "role_lead", name: "Lead", color: "#333333" },
      demandRequirement: {
        id: "demand_2",
        projectId: "project_1",
        startDate: new Date("2026-04-01"),
        endDate: new Date("2026-04-11"),
        hoursPerDay: 6,
        percentage: 75,
        role: "Lead",
        roleId: "role_lead",
        headcount: 1,
        status: AllocationStatus.PROPOSED,
      },
    });
    const assignmentFindUnique = vi.fn().mockResolvedValue({
      id: "assignment_2",
      demandRequirementId: "demand_2",
      resourceId: "resource_2",
      projectId: "project_1",
      startDate: new Date("2026-04-01"),
      endDate: new Date("2026-04-11"),
      hoursPerDay: 6,
      percentage: 75,
      role: "Lead",
      roleId: "role_lead",
      dailyCostCents: 42000,
      status: AllocationStatus.PROPOSED,
      metadata: {},
      createdAt: new Date("2026-03-13"),
      updatedAt: new Date("2026-03-13"),
      resource: { id: "resource_2", displayName: "Carol", eid: "E-003", lcrCents: 7000 },
      project: { id: "project_1", name: "Project One", shortCode: "PRJ" },
      roleEntity: { id: "role_lead", name: "Lead", color: "#333333" },
      demandRequirement: {
        id: "demand_2",
        projectId: "project_1",
        startDate: new Date("2026-04-01"),
        endDate: new Date("2026-04-11"),
        hoursPerDay: 6,
        percentage: 75,
        role: "Lead",
        roleId: "role_lead",
        headcount: 1,
        status: AllocationStatus.COMPLETED,
      },
    });
    const demandRequirementUpdate = vi.fn().mockResolvedValue({
      id: "demand_2",
      projectId: "project_1",
      headcount: 1,
      status: AllocationStatus.COMPLETED,

    });
    const allocationUpdate = vi.fn();
    const allocationDelete = vi.fn().mockResolvedValue({});
    const auditLogCreate = vi.fn().mockResolvedValue({});

    const db = {
      demandRequirement: { findUnique: demandRequirementFindUnique },
      assignment: { findMany: assignmentFindMany },
      resource: { findUnique: resourceFindUnique },
      $transaction: vi.fn(async (callback) =>
        callback({
          project: { findUnique: projectFindUnique },
          resource: { findUnique: resourceFindUnique },
          demandRequirement: {
            findUnique: txDemandRequirementFindUnique,
            update: demandRequirementUpdate,
          },
          assignment: {
            findUnique: assignmentFindUnique,
            findMany: assignmentFindMany,
            create: assignmentCreate,
          },
          vacation: { findMany: vacationFindMany },
          auditLog: { create: auditLogCreate },
        }),
      ),
    };

    const result = await fillDemandRequirement(db as never, {
      demandRequirementId: "demand_2",
      resourceId: "resource_2",
    });

    expect(result.assignment.id).toBe("assignment_2");
    expect(result.updatedDemandRequirement).toMatchObject({
      id: "demand_2",
      status: AllocationStatus.COMPLETED,

    });
    expect(demandRequirementUpdate).toHaveBeenCalledWith(
      expect.objectContaining({
        where: { id: "demand_2" },
        data: { status: AllocationStatus.COMPLETED },
      }),
    );
  });

  it("fills an explicit demand even when its legacy placeholder link is stale", async () => {
    const demandRequirementFindUnique = vi.fn().mockResolvedValue({
      id: "demand_stale",
      projectId: "project_1",
      startDate: new Date("2026-04-15"),
      endDate: new Date("2026-04-25"),
      hoursPerDay: 4,
      role: "Comp",
      roleId: "role_comp",
      headcount: 1,
      status: AllocationStatus.PROPOSED,
      metadata: { source: "stale-link" },
    });

    const projectFindUnique = vi.fn().mockResolvedValue({ id: "project_1" });
    const resourceFindUnique = vi.fn().mockResolvedValue({
      id: "resource_3",
      lcrCents: 6500,
      availability: {
        monday: 8,
        tuesday: 8,
        wednesday: 8,
        thursday: 8,
        friday: 8,
        saturday: 0,
        sunday: 0,
      },
    });
    const txDemandRequirementFindUnique = vi.fn().mockResolvedValue({
      id: "demand_stale",
      projectId: "project_1",
    });
    const assignmentFindMany = vi.fn().mockResolvedValue([]);
    const allocationFindMany = vi.fn().mockResolvedValue([]);
    const vacationFindMany = vi.fn().mockResolvedValue([]);
    const assignmentCreate = vi.fn().mockResolvedValue({
      id: "assignment_stale",

      demandRequirementId: "demand_stale",
      resourceId: "resource_3",
      projectId: "project_1",
      startDate: new Date("2026-04-15"),
      endDate: new Date("2026-04-25"),
      hoursPerDay: 4,
      percentage: 50,
      role: "Comp",
      roleId: "role_comp",
      dailyCostCents: 26000,
      status: AllocationStatus.PROPOSED,
      metadata: { source: "stale-link" },
      createdAt: new Date("2026-03-13"),
      updatedAt: new Date("2026-03-13"),
      resource: { id: "resource_3", displayName: "Dana", eid: "E-004", lcrCents: 6500 },
      project: { id: "project_1", name: "Project One", shortCode: "PRJ" },
      roleEntity: { id: "role_comp", name: "Comp", color: "#111111" },
      demandRequirement: {
        id: "demand_stale",
        projectId: "project_1",
        startDate: new Date("2026-04-15"),
        endDate: new Date("2026-04-25"),
        hoursPerDay: 4,
        percentage: 50,
        role: "Comp",
        roleId: "role_comp",
        headcount: 1,
        status: AllocationStatus.PROPOSED,
      },
    });
    const demandRequirementUpdate = vi.fn().mockResolvedValue({
      id: "demand_stale",
      projectId: "project_1",
      headcount: 1,
      status: AllocationStatus.COMPLETED,

    });
    const auditLogCreate = vi.fn().mockResolvedValue({});

    const db = {
      demandRequirement: { findUnique: demandRequirementFindUnique },
      assignment: { findMany: assignmentFindMany },
      $transaction: vi.fn(async (callback) =>
        callback({
          project: { findUnique: projectFindUnique },
          resource: { findUnique: resourceFindUnique },
          demandRequirement: {
            findUnique: txDemandRequirementFindUnique,
            update: demandRequirementUpdate,
          },
          assignment: {
            findMany: assignmentFindMany,
            create: assignmentCreate,
          },
          vacation: { findMany: vacationFindMany },
          auditLog: { create: auditLogCreate },
        }),
      ),
    };

    const result = await fillDemandRequirement(db as never, {
      demandRequirementId: "demand_stale",
      resourceId: "resource_3",
    });

    expect(result.assignment.id).toBe("assignment_stale");
    
    expect(result.updatedDemandRequirement).toMatchObject({
      id: "demand_stale",
      status: AllocationStatus.COMPLETED,

    });
    expect(demandRequirementUpdate).toHaveBeenCalledWith(
      expect.objectContaining({
        where: { id: "demand_stale" },
        data: { status: AllocationStatus.COMPLETED },
      }),
    );
  });

  it("fills an open demand by allocation id through the linked demand requirement", async () => {
    const initialDemandRequirement = {
      id: "demand_compat",
      projectId: "project_1",
      startDate: new Date("2026-05-01"),
      endDate: new Date("2026-05-09"),
      hoursPerDay: 4,
      percentage: 50,
      role: "Comp",
      roleId: "role_comp",
      headcount: 2,
      status: AllocationStatus.PROPOSED,
      metadata: {},
    };
    const updatedDemandRequirement = {
      id: "demand_compat",
      projectId: "project_1",
      headcount: 1,
      status: AllocationStatus.PROPOSED,

    };
    // loadAllocationEntry reads demand by id for resolution,
    // then fillDemandRequirement reads it again for the fill operation.
    const demandIdReads = [initialDemandRequirement, initialDemandRequirement, updatedDemandRequirement];
    const demandRequirementFindUnique = vi.fn().mockImplementation(({ where }) => {
      if (where.id === "demand_compat") {
        return Promise.resolve(demandIdReads.shift() ?? null);
      }

      return Promise.resolve(null);
    });
    const assignmentFindUnique = vi.fn().mockResolvedValue(null);
    const resourceFindUnique = vi.fn().mockResolvedValue({
      id: "resource_compat",
      lcrCents: 6000,
      availability: {
        monday: 8,
        tuesday: 8,
        wednesday: 8,
        thursday: 8,
        friday: 8,
        saturday: 0,
        sunday: 0,
      },
    });
    const txDemandRequirementFindUnique = vi.fn().mockResolvedValue({
      id: "demand_compat",
      projectId: "project_1",
    });
    const projectFindUnique = vi.fn().mockResolvedValue({ id: "project_1" });
    const assignmentFindMany = vi.fn().mockResolvedValue([]);
    const allocationFindMany = vi.fn().mockResolvedValue([]);
    const vacationFindMany = vi.fn().mockResolvedValue([]);
    const assignmentCreate = vi.fn().mockResolvedValue({
      id: "assignment_compat",

      demandRequirementId: "demand_compat",
      resourceId: "resource_compat",
      projectId: "project_1",
      startDate: new Date("2026-05-01"),
      endDate: new Date("2026-05-09"),
      hoursPerDay: 4,
      percentage: 50,
      role: "Comp",
      roleId: "role_comp",
      dailyCostCents: 24000,
      status: AllocationStatus.PROPOSED,
      metadata: {},
      createdAt: new Date("2026-03-13"),
      updatedAt: new Date("2026-03-13"),
      resource: { id: "resource_compat", displayName: "Dana", eid: "E-004", lcrCents: 6000 },
      project: { id: "project_1", name: "Project One", shortCode: "PRJ" },
      roleEntity: { id: "role_comp", name: "Comp", color: "#444444" },
      demandRequirement: {
        id: "demand_compat",
        projectId: "project_1",
        startDate: new Date("2026-05-01"),
        endDate: new Date("2026-05-09"),
        hoursPerDay: 4,
        percentage: 50,
        role: "Comp",
        roleId: "role_comp",
        headcount: 2,
        status: AllocationStatus.PROPOSED,
      },
    });
    const demandRequirementUpdate = vi.fn().mockResolvedValue(updatedDemandRequirement);
    const allocationDelete = vi.fn().mockResolvedValue({});
    const auditLogCreate = vi.fn().mockResolvedValue({});

    const db = {
      demandRequirement: { findUnique: demandRequirementFindUnique },
      assignment: { findUnique: assignmentFindUnique, findMany: assignmentFindMany },
      resource: { findUnique: resourceFindUnique },
      $transaction: vi.fn(async (callback) =>
        callback({
          project: { findUnique: projectFindUnique },
          resource: { findUnique: resourceFindUnique },
          demandRequirement: {
            findUnique: txDemandRequirementFindUnique,
            update: demandRequirementUpdate,
          },
          assignment: {
            findMany: assignmentFindMany,
            create: assignmentCreate,
          },
          vacation: { findMany: vacationFindMany },
          auditLog: { create: auditLogCreate },
        }),
      ),
    };

    const result = await fillOpenDemand(db as never, {
      allocationId: "demand_compat",
      resourceId: "resource_compat",
      status: AllocationStatus.PROPOSED,
    });

    expect(result).toEqual({
      strategy: "demand_requirement",
      createdAllocation: {
        id: "assignment_compat",
        projectId: "project_1",
        resourceId: "resource_compat",
      },
      updatedAllocation: {
        id: "demand_compat",
        projectId: "project_1",
        resourceId: null,
      },
    });
  });

  it("fills an explicit demand row by id through allocation entry resolution", async () => {
    const explicitDemand = {
      id: "demand_explicit",

      projectId: "project_1",
      startDate: new Date("2026-05-04"),
      endDate: new Date("2026-05-08"),
      hoursPerDay: 4,
      percentage: 50,
      role: "Comp",
      roleId: "role_comp",
      headcount: 2,
      status: AllocationStatus.PROPOSED,
      metadata: { source: "explicit-demand" },
      createdAt: new Date("2026-03-13"),
      updatedAt: new Date("2026-03-13"),
      project: { id: "project_1", name: "Project One", shortCode: "PRJ" },
      roleEntity: { id: "role_comp", name: "Comp", color: "#444444" },
    };
    const demandRequirementFindUnique = vi
      .fn()
      .mockImplementation(({ where }: { where: { id?: string } }) =>
        where.id === "demand_explicit" ? explicitDemand : null,
      );
    const assignmentFindUnique = vi.fn().mockResolvedValue(null);
    const projectFindUnique = vi.fn().mockResolvedValue({ id: "project_1" });
    const resourceFindUnique = vi.fn().mockResolvedValue({
      id: "resource_compat",
      lcrCents: 6000,
      availability: {
        monday: 8,
        tuesday: 8,
        wednesday: 8,
        thursday: 8,
        friday: 8,
        saturday: 0,
        sunday: 0,
      },
    });
    const assignmentFindMany = vi.fn().mockResolvedValue([]);
    const allocationFindMany = vi.fn().mockResolvedValue([]);
    const vacationFindMany = vi.fn().mockResolvedValue([]);
    const assignmentCreate = vi.fn().mockResolvedValue({
      id: "assignment_created",

      demandRequirementId: "demand_explicit",
      resourceId: "resource_compat",
      projectId: "project_1",
      startDate: new Date("2026-05-04"),
      endDate: new Date("2026-05-08"),
      hoursPerDay: 4,
      percentage: 50,
      role: "Comp",
      roleId: "role_comp",
      dailyCostCents: 24000,
      status: AllocationStatus.PROPOSED,
      metadata: { source: "explicit-demand" },
      createdAt: new Date("2026-03-13"),
      updatedAt: new Date("2026-03-13"),
      resource: { id: "resource_compat", displayName: "Dana", eid: "E-004", lcrCents: 6000 },
      project: { id: "project_1", name: "Project One", shortCode: "PRJ" },
      roleEntity: { id: "role_comp", name: "Comp", color: "#444444" },
      demandRequirement: explicitDemand,
    });
    const demandRequirementUpdate = vi.fn().mockResolvedValue({
      id: "demand_explicit",
      projectId: "project_1",
      headcount: 1,
      status: AllocationStatus.PROPOSED,

    });
    const auditLogCreate = vi.fn().mockResolvedValue({});

    const db = {
      allocation: {
        findUnique: vi.fn().mockResolvedValue(null),
        findMany: allocationFindMany,
      },
      demandRequirement: { findUnique: demandRequirementFindUnique },
      assignment: { findUnique: assignmentFindUnique, findMany: assignmentFindMany },
      resource: { findUnique: resourceFindUnique },
      $transaction: vi.fn(async (callback) =>
        callback({
          project: { findUnique: projectFindUnique },
          resource: { findUnique: resourceFindUnique },
          demandRequirement: {
            findUnique: demandRequirementFindUnique,
            update: demandRequirementUpdate,
          },
          assignment: {
            findMany: assignmentFindMany,
            create: assignmentCreate,
          },
          allocation: {
            findMany: allocationFindMany,
            delete: vi.fn().mockResolvedValue({}),
          },
          vacation: { findMany: vacationFindMany },
          auditLog: { create: auditLogCreate },
        }),
      ),
    };

    const result = await fillOpenDemand(db as never, {
      allocationId: "demand_explicit",
      resourceId: "resource_compat",
      status: AllocationStatus.PROPOSED,
    });

    expect(result).toEqual({
      strategy: "demand_requirement",
      createdAllocation: {
        id: "assignment_created",
        projectId: "project_1",
        resourceId: "resource_compat",
      },
      updatedAllocation: {
        id: "demand_explicit",
        projectId: "project_1",
        resourceId: null,
      },
    });
    expect(assignmentCreate).toHaveBeenCalledWith(
      expect.objectContaining({
        data: expect.objectContaining({
          demandRequirementId: "demand_explicit",
        }),
      }),
    );
    expect(demandRequirementUpdate).toHaveBeenCalledWith(
      expect.objectContaining({
        where: { id: "demand_explicit" },
      }),
    );
  });

  it("fills an explicit demand with a linked legacy placeholder by id without creating a new legacy assignment mirror", async () => {
    const explicitDemand = {
      id: "demand_explicit_legacy",
      projectId: "project_1",
      startDate: new Date("2026-05-11"),
      endDate: new Date("2026-05-15"),
      hoursPerDay: 4,
      percentage: 50,
      role: "Comp",
      roleId: "role_comp",
      headcount: 2,
      status: AllocationStatus.PROPOSED,
      metadata: { source: "explicit-demand-legacy" },
      createdAt: new Date("2026-03-13"),
      updatedAt: new Date("2026-03-13"),
      project: { id: "project_1", name: "Project One", shortCode: "PRJ" },
      roleEntity: { id: "role_comp", name: "Comp", color: "#444444" },
    };
    const demandRequirementFindUnique = vi
      .fn()
      .mockImplementation(({ where }: { where: { id?: string } }) =>
        where.id === "demand_explicit_legacy" ? explicitDemand : null,
      );
    const assignmentFindUnique = vi.fn().mockResolvedValue(null);
    const projectFindUnique = vi.fn().mockResolvedValue({ id: "project_1" });
    const resourceFindUnique = vi.fn().mockResolvedValue({
      id: "resource_compat",
      lcrCents: 6000,
      availability: {
        monday: 8,
        tuesday: 8,
        wednesday: 8,
        thursday: 8,
        friday: 8,
        saturday: 0,
        sunday: 0,
      },
    });
    const assignmentFindMany = vi.fn().mockResolvedValue([]);
    const allocationFindMany = vi.fn().mockResolvedValue([]);
    const vacationFindMany = vi.fn().mockResolvedValue([]);
    const assignmentCreate = vi.fn().mockResolvedValue({
      id: "assignment_created_explicit",

      demandRequirementId: "demand_explicit_legacy",
      resourceId: "resource_compat",
      projectId: "project_1",
      startDate: new Date("2026-05-11"),
      endDate: new Date("2026-05-15"),
      hoursPerDay: 4,
      percentage: 50,
      role: "Comp",
      roleId: "role_comp",
      dailyCostCents: 24000,
      status: AllocationStatus.PROPOSED,
      metadata: { source: "explicit-demand-legacy" },
      createdAt: new Date("2026-03-13"),
      updatedAt: new Date("2026-03-13"),
      resource: { id: "resource_compat", displayName: "Dana", eid: "E-004", lcrCents: 6000 },
      project: { id: "project_1", name: "Project One", shortCode: "PRJ" },
      roleEntity: { id: "role_comp", name: "Comp", color: "#444444" },
      demandRequirement: explicitDemand,
    });
    const allocationFindUnique = vi
      .fn()
      .mockImplementation(({ where }: { where: { id: string } }) =>
        where.id === "alloc_linked_placeholder"
          ? {
              id: "alloc_linked_placeholder",
              resourceId: null,
              projectId: "project_1",
              startDate: new Date("2026-05-11"),
              endDate: new Date("2026-05-15"),
              hoursPerDay: 4,
              percentage: 50,
              role: "Comp",
              roleId: "role_comp",
              isPlaceholder: true,
              headcount: 2,
              dailyCostCents: 0,
              status: AllocationStatus.PROPOSED,
              metadata: {},
            }
          : null,
      );
    const allocationDelete = vi.fn().mockResolvedValue({});
    const allocationCreate = vi.fn();
    const allocationUpdate = vi.fn();
    const assignmentUpdate = vi.fn();
    const demandRequirementUpdate = vi.fn().mockResolvedValue({
      id: "demand_explicit_legacy",
      projectId: "project_1",
      headcount: 1,
      status: AllocationStatus.PROPOSED,

    });
    const auditLogCreate = vi.fn().mockResolvedValue({});

    const db = {
      allocation: {
        findUnique: allocationFindUnique,
        findMany: allocationFindMany,
      },
      demandRequirement: { findUnique: demandRequirementFindUnique },
      assignment: { findUnique: assignmentFindUnique, findMany: assignmentFindMany },
      resource: { findUnique: resourceFindUnique },
      $transaction: vi.fn(async (callback) =>
        callback({
          project: { findUnique: projectFindUnique },
          resource: { findUnique: resourceFindUnique },
          demandRequirement: {
            findUnique: demandRequirementFindUnique,
            update: demandRequirementUpdate,
          },
          assignment: {
            findMany: assignmentFindMany,
            create: assignmentCreate,
            update: assignmentUpdate,
          },
          allocation: {
            findMany: allocationFindMany,
            create: allocationCreate,
            update: allocationUpdate,
            delete: allocationDelete,
          },
          vacation: { findMany: vacationFindMany },
          auditLog: { create: auditLogCreate },
        }),
      ),
    };

    const result = await fillOpenDemand(db as never, {
      allocationId: "demand_explicit_legacy",
      resourceId: "resource_compat",
      status: AllocationStatus.PROPOSED,
    });

    expect(result).toEqual({
      strategy: "demand_requirement",
      createdAllocation: {
        id: "assignment_created_explicit",
        projectId: "project_1",
        resourceId: "resource_compat",
      },
      updatedAllocation: {
        id: "demand_explicit_legacy",
        projectId: "project_1",
        resourceId: null,
      },
    });
    expect(demandRequirementUpdate).toHaveBeenCalledWith({
      where: { id: "demand_explicit_legacy" },
      data: {
        headcount: 1,
      },
      select: {
        id: true,
        projectId: true,
        headcount: true,
        status: true,
      },
    });
  });

  it("fills an open demand by demand requirement id when a linked demand requirement exists", async () => {
    const linkedDemandRequirement = {
      id: "demand_backfilled",
      projectId: "project_2",
      startDate: new Date("2026-06-01"),
      endDate: new Date("2026-06-05"),
      hoursPerDay: 8,
      percentage: 100,
      role: "Editor",
      roleId: "role_editor",
      headcount: 1,
      status: AllocationStatus.PROPOSED,
      metadata: {},
      project: { id: "project_2", name: "Project Two", shortCode: "PR2" },
      roleEntity: { id: "role_editor", name: "Editor", color: "#555555" },
    };
    const demandRequirementFindUnique = vi
      .fn()
      .mockImplementation(({ where }: { where: { id?: string } }) => {
        if (where.id === "demand_backfilled") {
          return linkedDemandRequirement;
        }
        return null;
      });
    const assignmentFindUnique = vi.fn().mockResolvedValue(null);
    const assignmentCreate = vi.fn().mockResolvedValue({
      id: "assignment_fallback",

      demandRequirementId: "demand_backfilled",
      resourceId: "resource_editor",
      projectId: "project_2",
      startDate: new Date("2026-06-01"),
      endDate: new Date("2026-06-05"),
      hoursPerDay: 8,
      percentage: 100,
      role: "Editor",
      roleId: "role_editor",
      dailyCostCents: 40000,
      status: AllocationStatus.PROPOSED,
      metadata: {},
      createdAt: new Date("2026-03-13"),
      updatedAt: new Date("2026-03-13"),
      resource: { id: "resource_editor", displayName: "Evan", eid: "E-005", lcrCents: 5000 },
      project: { id: "project_2", name: "Project Two", shortCode: "PR2" },
      roleEntity: { id: "role_editor", name: "Editor", color: "#555555" },
      demandRequirement: null,
    });
    const resourceFindUnique = vi.fn().mockResolvedValue({
      id: "resource_editor",
      lcrCents: 5000,
      availability: {
        monday: 8,
        tuesday: 8,
        wednesday: 8,
        thursday: 8,
        friday: 8,
        saturday: 0,
        sunday: 0,
      },
    });
    const projectFindUnique = vi.fn().mockResolvedValue({ id: "project_2" });
    const assignmentFindMany = vi.fn().mockResolvedValue([]);
    const vacationFindMany = vi.fn().mockResolvedValue([]);
    const demandRequirementUpdate = vi.fn().mockResolvedValue({
      id: "demand_backfilled",
      projectId: "project_2",
      headcount: 1,
      status: AllocationStatus.COMPLETED,

    });
    const auditLogCreate = vi.fn().mockResolvedValue({});

    const db = {
      demandRequirement: {
        findUnique: demandRequirementFindUnique,
      },
      assignment: { findUnique: assignmentFindUnique, findMany: assignmentFindMany },
      auditLog: { create: auditLogCreate },
      $transaction: vi.fn(async (callback) =>
        callback({
          project: { findUnique: projectFindUnique },
          resource: { findUnique: resourceFindUnique },
          assignment: {
            findMany: assignmentFindMany,
            create: assignmentCreate,
          },
          demandRequirement: {
            findUnique: demandRequirementFindUnique,
            update: demandRequirementUpdate,
          },
          vacation: { findMany: vacationFindMany },
          auditLog: { create: auditLogCreate },
        }),
      ),
    };

    const result = await fillOpenDemand(db as never, {
      allocationId: "demand_backfilled",
      resourceId: "resource_editor",
      status: AllocationStatus.PROPOSED,
    });

    expect(result).toEqual({
      strategy: "demand_requirement",
      createdAllocation: {
        id: "assignment_fallback",
        projectId: "project_2",
        resourceId: "resource_editor",
      },
      updatedAllocation: {
        id: "demand_backfilled",
        projectId: "project_2",
        resourceId: null,
      },
    });
    expect(assignmentCreate).toHaveBeenCalledWith(
      expect.objectContaining({
        data: expect.objectContaining({
          demandRequirementId: "demand_backfilled",
          resourceId: "resource_editor",
        }),
      }),
    );
  });

  it("fills a multi-headcount demand requirement resolved by legacy allocation id", async () => {
    const linkedDemandRequirement = {
      id: "demand_backfilled_multi",
      projectId: "project_3",
      startDate: new Date("2026-06-08"),
      endDate: new Date("2026-06-12"),
      hoursPerDay: 4,
      percentage: 50,
      role: "Animator",
      roleId: "role_anim",
      headcount: 2,
      status: AllocationStatus.PROPOSED,
      metadata: {},
      project: { id: "project_3", name: "Project Three", shortCode: "PR3" },
      roleEntity: { id: "role_anim", name: "Animator", color: "#666666" },
    };
    const demandRequirementFindUnique = vi
      .fn()
      .mockImplementation(({ where }: { where: { id?: string } }) => {
        if (where.id === "demand_backfilled_multi") {
          return linkedDemandRequirement;
        }
        return null;
      });
    const assignmentFindUnique = vi.fn().mockResolvedValue(null);
    const assignmentCreate = vi.fn().mockResolvedValue({
      id: "assignment_fallback_multi",

      demandRequirementId: "demand_backfilled_multi",
      resourceId: "resource_multi",
      projectId: "project_3",
      startDate: new Date("2026-06-08"),
      endDate: new Date("2026-06-12"),
      hoursPerDay: 4,
      percentage: 50,
      role: "Animator",
      roleId: "role_anim",
      dailyCostCents: 22000,
      status: AllocationStatus.PROPOSED,
      metadata: {},
      createdAt: new Date("2026-03-13"),
      updatedAt: new Date("2026-03-13"),
      resource: { id: "resource_multi", displayName: "Finn", eid: "E-006", lcrCents: 5500 },
      project: { id: "project_3", name: "Project Three", shortCode: "PR3" },
      roleEntity: { id: "role_anim", name: "Animator", color: "#666666" },
      demandRequirement: null,
    });
    const resourceFindUnique = vi.fn().mockResolvedValue({
      id: "resource_multi",
      lcrCents: 5500,
      availability: {
        monday: 8,
        tuesday: 8,
        wednesday: 8,
        thursday: 8,
        friday: 8,
        saturday: 0,
        sunday: 0,
      },
    });
    const projectFindUnique = vi.fn().mockResolvedValue({ id: "project_3" });
    const assignmentFindMany = vi.fn().mockResolvedValue([]);
    const vacationFindMany = vi.fn().mockResolvedValue([]);
    const demandRequirementUpdate = vi.fn().mockResolvedValue({
      id: "demand_backfilled_multi",
      projectId: "project_3",
      headcount: 1,
      status: AllocationStatus.PROPOSED,

    });
    const auditLogCreate = vi.fn().mockResolvedValue({});

    const db = {
      demandRequirement: {
        findUnique: demandRequirementFindUnique,
      },
      assignment: { findUnique: assignmentFindUnique, findMany: assignmentFindMany },
      auditLog: { create: auditLogCreate },
      $transaction: vi.fn(async (callback) =>
        callback({
          project: { findUnique: projectFindUnique },
          resource: { findUnique: resourceFindUnique },
          assignment: {
            findMany: assignmentFindMany,
            create: assignmentCreate,
          },
          demandRequirement: {
            findUnique: demandRequirementFindUnique,
            update: demandRequirementUpdate,
          },
          vacation: { findMany: vacationFindMany },
          auditLog: { create: auditLogCreate },
        }),
      ),
    };

    const result = await fillOpenDemand(db as never, {
      allocationId: "demand_backfilled_multi",
      resourceId: "resource_multi",
      status: AllocationStatus.PROPOSED,
    });

    expect(result).toEqual({
      strategy: "demand_requirement",
      createdAllocation: {
        id: "assignment_fallback_multi",
        projectId: "project_3",
        resourceId: "resource_multi",
      },
      updatedAllocation: {
        id: "demand_backfilled_multi",
        projectId: "project_3",
        resourceId: null,
      },
    });
    expect(assignmentCreate).toHaveBeenCalledWith(
      expect.objectContaining({
        data: expect.objectContaining({
          demandRequirementId: "demand_backfilled_multi",
          resourceId: "resource_multi",
        }),
      }),
    );
  });
});
