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

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

vi.mock("@capakraken/engine", async (importOriginal) => {
  const actual = await importOriginal<typeof import("@capakraken/engine")>();
  return {
    ...actual,
    calculateAllocation: calculateAllocationMock,
  };
});

import {
  buildTimelineProjectDateRangeUpdate,
  buildTimelineProjectShiftAuditChanges,
  buildTimelineShiftedAssignmentUpdate,
  recalculateShiftedAssignmentDailyCost,
} from "../router/timeline-shift-mutation-support.js";

describe("timeline shift mutation support", () => {
  it("builds shared date range updates for project and demand records", () => {
    expect(
      buildTimelineProjectDateRangeUpdate({
        newStartDate: new Date("2026-04-03T00:00:00.000Z"),
        newEndDate: new Date("2026-04-12T00:00:00.000Z"),
      }),
    ).toEqual({
      startDate: new Date("2026-04-03T00:00:00.000Z"),
      endDate: new Date("2026-04-12T00:00:00.000Z"),
    });
  });

  it("builds assignment updates with optional recalculated daily cost", () => {
    expect(
      buildTimelineShiftedAssignmentUpdate({
        newStartDate: new Date("2026-04-03T00:00:00.000Z"),
        newEndDate: new Date("2026-04-12T00:00:00.000Z"),
        dailyCostCents: 54321,
      }),
    ).toEqual({
      startDate: new Date("2026-04-03T00:00:00.000Z"),
      endDate: new Date("2026-04-12T00:00:00.000Z"),
      dailyCostCents: 54321,
    });

    expect(
      buildTimelineShiftedAssignmentUpdate({
        newStartDate: new Date("2026-04-03T00:00:00.000Z"),
        newEndDate: new Date("2026-04-12T00:00:00.000Z"),
        dailyCostCents: undefined,
      }),
    ).toEqual({
      startDate: new Date("2026-04-03T00:00:00.000Z"),
      endDate: new Date("2026-04-12T00:00:00.000Z"),
    });
  });

  it("builds project shift audit payloads", () => {
    expect(
      buildTimelineProjectShiftAuditChanges({
        project: {
          id: "project_1",
          budgetCents: 200_000,
          winProbability: 80,
          startDate: new Date("2026-04-01T00:00:00.000Z"),
          endDate: new Date("2026-04-10T00:00:00.000Z"),
        },
        newStartDate: new Date("2026-04-03T00:00:00.000Z"),
        newEndDate: new Date("2026-04-12T00:00:00.000Z"),
        validation: {
          valid: true,
          errors: [],
          warnings: [],
          conflictDetails: [],
          costImpact: {
            currentTotalCents: 100_000,
            newTotalCents: 112_000,
            deltaCents: 12_000,
            budgetCents: 200_000,
            budgetUtilizationBefore: 50,
            budgetUtilizationAfter: 56,
            wouldExceedBudget: false,
          },
        },
      }),
    ).toEqual({
      before: {
        startDate: new Date("2026-04-01T00:00:00.000Z"),
        endDate: new Date("2026-04-10T00:00:00.000Z"),
      },
      after: {
        startDate: new Date("2026-04-03T00:00:00.000Z"),
        endDate: new Date("2026-04-12T00:00:00.000Z"),
      },
      costImpact: {
        currentTotalCents: 100_000,
        newTotalCents: 112_000,
        deltaCents: 12_000,
        budgetCents: 200_000,
        budgetUtilizationBefore: 50,
        budgetUtilizationAfter: 56,
        wouldExceedBudget: false,
      },
    });
  });

  it("recalculates daily cost only for staffed assignments", async () => {
    calculateAllocationMock.mockReturnValueOnce({ dailyCostCents: 54321 });

    await expect(
      recalculateShiftedAssignmentDailyCost({
        db: {
          vacation: { findMany: vi.fn().mockResolvedValue([]) },
          calculationRule: { findMany: vi.fn().mockResolvedValue([{ id: "rule_1" }]) },
        } as never,
        assignment: {
          resourceId: "resource_1",
          hoursPerDay: 8,
          metadata: { includeSaturday: true },
          resource: {
            lcrCents: 5_000,
            availability: {
              monday: 8,
              tuesday: 8,
              wednesday: 8,
              thursday: 8,
              friday: 8,
            },
          },
        } as never,
        newStartDate: new Date("2026-04-03T00:00:00.000Z"),
        newEndDate: new Date("2026-04-12T00:00:00.000Z"),
      }),
    ).resolves.toBe(54321);

    await expect(
      recalculateShiftedAssignmentDailyCost({
        db: {} as never,
        assignment: {
          resourceId: null,
          resource: null,
        } as never,
        newStartDate: new Date("2026-04-03T00:00:00.000Z"),
        newEndDate: new Date("2026-04-12T00:00:00.000Z"),
      }),
    ).resolves.toBeUndefined();
  });
});
