export type FreightType = "CONTAINER" | "BULK" | "MIXED";

export type SchedulingStatus =
  | "NOT_SCHEDULED"
  | "HOLDING"
  | "ELIGIBLE"
  | "SCHEDULED"
  | "DISPATCHED";

export type TrainScheduleStatus =
  | "DRAFT"
  | "SCHEDULED"
  | "DISPATCHED"
  | "ARRIVED"
  | "CANCELLED";

export interface YardOption {
  id: string;
  name: string;
  code: string;
  country?: string;
}

export interface EligibleContainerBooking {
  id: string;
  reference: string;
  freightType?: FreightType | string;
  customer: string;
  containerType: string;
  quantity: number;
  weightTons: number;
  origin: string;
  destination: string;
  preferredDepartureDate: string;
  status: string;
  schedulingStatus?: SchedulingStatus;
  priorityScore?: number;
}

export interface EligibleContainerBookingsResponse {
  count: number;
  items: EligibleContainerBooking[];
}

export interface WagonPlanAllocation {
  bookingId: string;
  bookingReference: string;
  allocatedWeightTons: number;
  loadType?: string;
}

export interface WagonPlanRow {
  sequenceNo: number;
  capacityTons: number;
  lengthMeters: number;
  assignedWeightTons: number;
  slotLoadType?: "CONTAINER" | "BULK";
  wagonTypeCode?: string;
  allocations: WagonPlanAllocation[];
}

export interface ContainerUnitRow {
  bookingId: string;
  bookingReference: string;
  bookingContainerId: string;
  unitIndex: number;
  containerTypeId: string;
  containerTypeCode: string;
  label: string;
  grossWeightTons: number;
  sizeFt?: number;
  wagonsPerUnit?: number;
  containersPerWagon?: number;
  teuSlots?: number;
  containerNumber?: string | null;
}

export interface ContainerPlacement {
  bookingContainerId: string;
  unitIndex: number;
  sequenceNo: number;
  containerId?: string;
  containerNumber?: string;
  sealNumber?: string;
}

export interface FleetAvailabilityRow {
  wagonTypeId: string;
  wagonTypeCode: string;
  needed: number;
  available: number;
  shortfall: number;
}

export interface DeferredBookingRow {
  id: string;
  reference: string;
  reason: string;
}

export interface TrainSchedulingGlobalRules {
  id: string;
  maxTrainLengthMeters: number;
  maxTrainWeightTons: number;
  maxWagonsPerTrain: number;
  max20ftContainerWeightTons: number;
  max20ftPairWeightDiffTons: number;
}

export interface TrainSchedulePreviewResponse {
  valid: boolean;
  violations: string[];
  warnings: string[];
  fleetAvailability?: FleetAvailabilityRow[];
  deferredBookings?: DeferredBookingRow[];
  summary: {
    totalBookings: number;
    totalWeightTons: number;
    wagonType: string;
    wagonsNeeded: number;
    totalLengthMeters: number;
    freightMode?: FreightType;
  };
  bookingIds: string[];
  wagonPlan: WagonPlanRow[];
  containerUnits?: ContainerUnitRow[];
  containerSlotSequenceNos?: number[];
}

export interface LocomotiveRecord {
  id: string;
  code: string;
  name?: string | null;
  maxPullWeightTons: number;
  maxTrainLengthMeters: number;
  status: "AVAILABLE" | "ASSIGNED" | "MAINTENANCE" | "OUT_OF_SERVICE";
  currentYardId?: string | null;
  locomotiveType?: "DIESEL" | "ELECTRIC";
}

export interface TrainScheduleListItem {
  id: string;
  scheduleDate: string;
  trainNumber?: string | null;
  routeName?: string | null;
  origin: string | null;
  destination: string | null;
  freightType?: FreightType | null;
  locomotive: {
    id: string;
    code: string;
    name?: string | null;
    currentYardId?: string | null;
  } | null;
  wagonCount: number;
  totalWeightTons: number;
  totalLengthMeters: number;
  bookingsCount: number;
  status: TrainScheduleStatus | string;
}

export interface BookableSchedule {
  id: string;
  scheduleDate: string;
  trainNumber?: string | null;
  routeName?: string | null;
  origin: string | null;
  destination: string | null;
  freightType?: FreightType | null;
  status: TrainScheduleStatus | string;
  bookingWindowStatus: "OPEN" | "FULL" | "CLOSED" | string;
  maxWagons: number;
  remainingWagons: number;
  locomotive: { id: string; code: string; name?: string | null } | null;
}

export type BatchBoardBookingState =
  | "ALLOCATED"
  | "SELECTED_FOR_BATCH"
  | "READY"
  | "WAITING"
  | "PENDING_CONTRACT"
  | "EXPIRED";

export interface BatchBoardBooking {
  id: string;
  reference: string;
  company: string;
  isGovernment: boolean;
  wagons: number;
  weightTons: number;
  lengthMeters: number;
  paymentDeadline: string | null;
  state: BatchBoardBookingState;
}

export interface BatchBoardSchedule {
  scheduleId: string;
  trainNumber: string | null;
  routeName: string | null;
  origin: string | null;
  destination: string | null;
  scheduleDate: string | null;
  status: string;
  bookingWindowStatus: string;
  locomotive: {
    code: string;
    name: string | null;
    maxPullWeightTons: number;
    maxTrainLengthMeters: number;
  } | null;
  capacity: {
    allocatedWagons: number;
    allocatedLengthMeters: number;
    maxLengthMeters: number | null;
    usedWeightTons: number;
    maxWeightTons: number | null;
  };
  counts: {
    allocated: number;
    selectedForBatch: number;
    ready: number;
    waiting: number;
    pendingContract: number;
    expired: number;
  };
  bookings: BatchBoardBooking[];
}

export type BookingAllocationStatus =
  | "NOT_ATTEMPTED"
  | "ASSIGNED"
  | "DEFERRED"
  | "FAILED";

export interface BatchBoardBookingDetail extends BatchBoardBooking {
  fullyExecutedAt: string | null;
  selectedForBatchAt: string | null;
  allocationStatus: BookingAllocationStatus;
  allocationIssue: string | null;
}

export interface BatchWindowGroup {
  key: string;
  label: string;
  /** EAT calendar day as ISO `YYYY-MM-DD` (empty for the pending-contract bucket). */
  date: string;
  /** Human label for the day, e.g. `Thu, 05 Jun` (empty for pending-contract). */
  dateLabel: string;
  start: string;
  end: string;
  counts: {
    allocated: number;
    selectedForBatch: number;
    ready: number;
    waiting: number;
    expired: number;
    pendingContract: number;
  };
  bookings: BatchBoardBookingDetail[];
}

export interface BatchBoardScheduleDetail {
  scheduleId: string;
  trainNumber: string | null;
  routeName: string | null;
  origin: string | null;
  destination: string | null;
  scheduleDate: string | null;
  status: string;
  bookingWindowStatus: string;
  locomotive: BatchBoardSchedule["locomotive"];
  capacity: BatchBoardSchedule["capacity"];
  counts: BatchBoardSchedule["counts"];
  windows: BatchWindowGroup[];
  pendingContract: BatchWindowGroup;
  allocationViolations: string[];
}

export interface WagonAllocationAttemptResult {
  assignedBookingIds: string[];
  deferred: Array<{ id: string; reference: string; reason: string }>;
  issues: Array<{
    bookingId: string;
    status: BookingAllocationStatus;
    issue: string | null;
  }>;
  violations: string[];
}

export interface TrainScheduleWagonAllocation {
  id: string;
  bookingId: string;
  bookingReference: string | null;
  allocatedWeightTons: number;
  loadType?: string | null;
  status?: string;
  containerItems?: Array<{
    id: string;
    containerNumber: string | null;
    containerTypeId: string;
    grossWeightTons: number | null;
    containerId?: string | null;
    positionOnWagon?: number | null;
    bookingContainerId?: string | null;
  }>;
  bulkLoad?: {
    id: string;
    weightTons: number;
    cargoDescription: string | null;
  } | null;
}

export interface TrainScheduleDetail {
  id: string;
  status: TrainScheduleStatus | string;
  deferredBookings?: DeferredBookingRow[];
  freightType?: FreightType | null;
  trainNumber?: string | null;
  direction?: string | null;
  route?: {
    id: string;
    name: string;
  } | null;
  scheduledDepartureDate: string;
  scheduledArrivalDate?: string | null;
  actualDepartureAt?: string | null;
  actualArrivalAt?: string | null;
  originStation?: {
    id: string;
    label?: string;
    code?: string;
  } | null;
  destinationStation?: {
    id: string;
    label?: string;
    code?: string;
  } | null;
  trainSet?: {
    id: string;
    status: string;
    wagonCount: number;
    totalWeightTons: number;
    totalLengthMeters: number;
    locomotive?: {
      id: string;
      code: string;
      name?: string | null;
      status: string;
      currentYardId?: string | null;
      maxPullWeightTons: number;
      maxTrainLengthMeters?: number;
    } | null;
    wagons: Array<{
      id: string;
      sequenceNo: number;
      capacityTons: number;
      lengthMeters: number;
      assignedWeightTons: number;
      status?: string;
      physicalWagonId?: string | null;
      physicalWagonNumber?: string | null;
      wagonType?: {
        id: string;
        code: string;
        name: string;
      } | null;
      allocations: TrainScheduleWagonAllocation[];
    }>;
  } | null;
  bookings: Array<{
    id: string;
    reference: string | null;
    customer: string | null;
    weightTons: number;
    status: string | null;
    schedulingStatus?: SchedulingStatus | null;
    freightType?: FreightType | string | null;
  }>;
  warnings?: string[];
}

export type TrainCheckpointKind = "DEPARTED" | "PASSED" | "ARRIVED";

export interface TrackStation {
  sequenceNo: number;
  yardId: string;
  label: string;
  code: string;
}

export interface TrainCheckpoint {
  id: string;
  sequenceNo: number;
  yardId: string;
  label: string | null;
  kind: TrainCheckpointKind;
  occurredAt: string;
  note: string | null;
}

export interface TrainTrackResponse {
  scheduleId: string;
  status: TrainScheduleStatus | string;
  direction?: string | null;
  trainNumber?: string | null;
  actualDepartureAt?: string | null;
  actualArrivalAt?: string | null;
  origin: string | null;
  destination: string | null;
  stations: TrackStation[];
  currentSequenceNo: number;
  checkpoints: TrainCheckpoint[];
}

export interface RecordCheckpointPayload {
  sequenceNo: number;
  kind?: TrainCheckpointKind;
  occurredAt?: string;
  note?: string;
}

export interface TrainScheduleFilters {
  originStationId?: string;
  destinationStationId?: string;
  schedulingStatus?: SchedulingStatus;
  /** Scope eligible bookings to a single schedule (batch parity). */
  trainScheduleId?: string;
}

export interface TrainSchedulePreviewPayload {
  bookingIds: string[];
  scheduleDate: string;
  originStationId: string;
  destinationStationId: string;
  targetScheduleId?: string;
  maxTrainWeightTons?: number;
  maxTrainLengthMeters?: number;
  maxWagonsPerTrain?: number;
}

export interface RescheduleBookingSummary {
  id: string;
  reference: string;
  isGovernment: boolean;
  priorityScore: number;
  governmentInstitution?: string | null;
}

export interface ReschedulePlan {
  scheduleId: string;
  trigger: string;
  retained: RescheduleBookingSummary[];
  displaced: RescheduleBookingSummary[];
  readmitted: RescheduleBookingSummary[];
  finalBookingIds: string[];
  warnings: string[];
}

export interface CreateTrainSchedulePayload {
  routeId: string;
  scheduleDate: string;
  locomotiveId: string;
  maxTrainWeightTons?: number;
  maxTrainLengthMeters?: number;
  maxWagonsPerTrain?: number;
}

export interface AssignBookingsPayload {
  bookingIds: string[];
  forceAssign?: boolean;
  containerPlacements?: ContainerPlacement[];
  maxTrainWeightTons?: number;
  maxTrainLengthMeters?: number;
  maxWagonsPerTrain?: number;
}

export interface PinWagonAssignment {
  trainSetWagonId: string;
  physicalWagonId: string;
}

export interface PinWagonsPayload {
  assignments: PinWagonAssignment[];
}

export interface CompositionUnassignedBooking {
  id: string;
  reference: string | null;
  freightType: FreightType | null;
  priorityScore: number;
  cargoTotalWeightVgm: number;
  status: string | null;
  schedulingStatus: SchedulingStatus | null;
  wagonsRequired: number;
  requiredWagonTypeCode: string;
  yardWagonsAvailable: number;
  canAssign: boolean;
  blockReason: string | null;
}

export interface UnassignedBookingsResponse {
  fleetAtOrigin: FleetAvailabilityRow[];
  bookings: CompositionUnassignedBooking[];
}

export interface CompositionRemovalEntry {
  id: string;
  scheduleId: string;
  bookingId: string;
  bookingReference: string | null;
  removedByUserId: string | null;
  removedAt: string;
  notes: string | null;
}
