import type {
  SplitAssignmentRecord,
  SplitDemandRequirementRecord,
} from "@capakraken/application";
import { validateShift } from "@capakraken/engine";
import type { ShiftValidationResult } from "@capakraken/shared";
import { TRPCError } from "@trpc/server";
import type { TimelineShiftPlan } from "./timeline-shift-planning.js";

export interface TimelineShiftProjectRecord {
  id: string;
  budgetCents: number;
  winProbability: number;
  startDate: Date;
  endDate: Date;
}

export interface LoadedTimelineShiftContext {
  project: TimelineShiftProjectRecord;
  demandRequirements: SplitDemandRequirementRecord[];
  assignments: SplitAssignmentRecord[];
  shiftPlan: TimelineShiftPlan;
}

export interface TimelineProjectShiftEventPayload extends Record<string, unknown> {
  projectId: string;
  newStartDate: string;
  newEndDate: string;
  costDeltaCents: number;
  resourceIds: Array<string | null>;
}

export function buildTimelineProjectShiftValidation(input: {
  context: LoadedTimelineShiftContext;
  newStartDate: Date;
  newEndDate: Date;
}) {
  const { context, newStartDate, newEndDate } = input;

  return validateShift({
    project: {
      id: context.project.id,
      budgetCents: context.project.budgetCents,
      winProbability: context.project.winProbability,
      startDate: context.project.startDate,
      endDate: context.project.endDate,
    },
    newStartDate,
    newEndDate,
    allocations: context.shiftPlan.validationAllocations,
  });
}

export function assertTimelineProjectShiftValid(
  validation: ShiftValidationResult,
): void {
  if (validation.valid) {
    return;
  }

  throw new TRPCError({
    code: "BAD_REQUEST",
    message: `Shift validation failed: ${validation.errors.map((error) => error.message).join(", ")}`,
  });
}

export function buildTimelineProjectShiftEventPayload(input: {
  projectId: string;
  newStartDate: Date;
  newEndDate: Date;
  validation: ShiftValidationResult;
  assignments: SplitAssignmentRecord[];
}): TimelineProjectShiftEventPayload {
  return {
    projectId: input.projectId,
    newStartDate: input.newStartDate.toISOString(),
    newEndDate: input.newEndDate.toISOString(),
    costDeltaCents: input.validation.costImpact.deltaCents,
    resourceIds: input.assignments.map((assignment) => assignment.resourceId),
  };
}
