import type { ShiftValidationResult } from "@capakraken/shared";
import { TRPCError } from "@trpc/server";
import { describe, expect, it, vi } from "vitest";

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

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

import {
  assertTimelineProjectShiftValid,
  buildTimelineProjectShiftEventPayload,
  buildTimelineProjectShiftValidation,
} from "../router/timeline-shift-support.js";

function createValidValidationResult(
  overrides: Partial<ShiftValidationResult> = {},
): ShiftValidationResult {
  return {
    valid: true,
    errors: [],
    warnings: [],
    conflictDetails: [],
    costImpact: {
      currentTotalCents: 100_000,
      newTotalCents: 112_000,
      deltaCents: 12_000,
      budgetCents: 200_000,
      budgetUtilizationBefore: 50,
      budgetUtilizationAfter: 56,
      wouldExceedBudget: false,
    },
    ...overrides,
  };
}

describe("timeline shift support", () => {
  it("builds validation requests from loaded shift context", () => {
    const expectedValidation = createValidValidationResult();
    validateShiftMock.mockReturnValue(expectedValidation);

    const result = buildTimelineProjectShiftValidation({
      context: {
        project: {
          id: "project_1",
          budgetCents: 200_000,
          winProbability: 80,
          startDate: new Date("2026-04-01"),
          endDate: new Date("2026-04-10"),
        },
        demandRequirements: [],
        assignments: [],
        shiftPlan: {
          validationAllocations: [
            {
              id: "assignment_1",
              resourceId: "resource_1",
              startDate: new Date("2026-04-01"),
              endDate: new Date("2026-04-05"),
              hoursPerDay: 8,
              percentage: 100,
              role: "Compositing",
              dailyCostCents: 40_000,
              resource: {
                id: "resource_1",
                displayName: "Alice",
                lcrCents: 5_000,
                availability: {
                  monday: 8,
                  tuesday: 8,
                  wednesday: 8,
                  thursday: 8,
                  friday: 8,
                },
              },
              allAllocationsForResource: [],
            },
          ],
        },
      },
      newStartDate: new Date("2026-04-03"),
      newEndDate: new Date("2026-04-12"),
    });

    expect(result).toBe(expectedValidation);
    expect(validateShiftMock).toHaveBeenCalledWith({
      project: {
        id: "project_1",
        budgetCents: 200_000,
        winProbability: 80,
        startDate: new Date("2026-04-01"),
        endDate: new Date("2026-04-10"),
      },
      newStartDate: new Date("2026-04-03"),
      newEndDate: new Date("2026-04-12"),
      allocations: [
        expect.objectContaining({
          id: "assignment_1",
          resourceId: "resource_1",
        }),
      ],
    });
  });

  it("throws a BAD_REQUEST error for invalid shift validations", () => {
    expect(() =>
      assertTimelineProjectShiftValid(createValidValidationResult({
        valid: false,
        errors: [
          {
            code: "AVAILABILITY_CONFLICT",
            message: "Alice exceeds capacity",
          },
        ],
      })),
    ).toThrowError(new TRPCError({
      code: "BAD_REQUEST",
      message: "Shift validation failed: Alice exceeds capacity",
    }));
  });

  it("builds project shifted event payloads", () => {
    const validation = createValidValidationResult();

    expect(
      buildTimelineProjectShiftEventPayload({
        projectId: "project_1",
        newStartDate: new Date("2026-04-03T00:00:00.000Z"),
        newEndDate: new Date("2026-04-12T00:00:00.000Z"),
        validation,
        assignments: [
          { resourceId: "resource_1" },
          { resourceId: null },
        ] as never,
      }),
    ).toEqual({
      projectId: "project_1",
      newStartDate: "2026-04-03T00:00:00.000Z",
      newEndDate: "2026-04-12T00:00:00.000Z",
      costDeltaCents: 12_000,
      resourceIds: ["resource_1", null],
    });
  });
});
