/**
 * Resolves the booking/check-in cutoff for one boarding stop.
 *
 * Priority for checkinMinutes: RouteStop.checkinMinutesBefore → Route.checkinMinutesBefore → 30.
 *
 * Anchor (segmentTime): plannedDepartureAt ?? plannedArrivalAt ?? schedule.departureAt.
 *   - For the origin stop: plannedDepartureAt = schedule.departureAt (no arrival).
 *   - For intermediate stops: plannedDepartureAt = plannedArrivalAt + dwell (checkinMinutesBefore).
 *     cutoffAt = departureAt − checkinMinutesBefore = arrivalAt, so booking closes the
 *     moment the train reaches the stop — independent of how long ago it left the origin.
 *
 * Single source of truth — SeatsService.holdSeats and SearchService.buildScheduleResult both
 * apply it; GuestBookingService.createGuestBooking also applies it per boarding stop.
 */
export interface CheckinCutoff {
  /** The stop's planned departure time (or arrival / schedule departure as fallback). */
  segmentTime: Date;
  /** Minutes before segmentTime that booking/holding closes. */
  checkinMinutes: number;
  /** The moment booking/holding closes for this stop. */
  cutoffAt: Date;
}

export function resolveCheckinCutoff(
  schedule: {
    departureAt: Date;
    route?: {
      checkinMinutesBefore?: number | null;
      stops?: Array<{ stationId: string; checkinMinutesBefore: number | null }>;
    } | null;
  },
  stopTime: { plannedArrivalAt?: Date | null; plannedDepartureAt?: Date | null } | null | undefined,
  stationId: string | null | undefined,
): CheckinCutoff {
  const segmentTime = stopTime?.plannedDepartureAt ?? stopTime?.plannedArrivalAt ?? schedule.departureAt;
  const routeStop = stationId ? schedule.route?.stops?.find((s) => s.stationId === stationId) : undefined;
  const checkinMinutes = routeStop?.checkinMinutesBefore ?? schedule.route?.checkinMinutesBefore ?? 30;
  return {
    segmentTime,
    checkinMinutes,
    cutoffAt: new Date(segmentTime.getTime() - checkinMinutes * 60_000),
  };
}
