import { compareSchedulingPriority } from "./compareSchedulingPriority"; export interface ThreeHourSchedulable { id: string; priorityScore?: number; scheduledDate?: string; preferredDepartureDate?: string; isGovernment?: boolean; } export interface ThreeHourBookingBucket { key: string; label: string; start: Date; end: Date; bookings: T[]; } function bucketStart(date: Date): Date { const start = new Date(date); start.setUTCMinutes(0, 0, 0); const hour = start.getUTCHours(); start.setUTCHours(Math.floor(hour / 3) * 3); return start; } function formatBucketLabel(start: Date, end: Date): string { const dateFmt = new Intl.DateTimeFormat("en-GB", { day: "2-digit", month: "short", year: "numeric", timeZone: "UTC", }); const timeFmt = new Intl.DateTimeFormat("en-GB", { hour: "2-digit", minute: "2-digit", hour12: false, timeZone: "UTC", }); return `${dateFmt.format(start)} · ${timeFmt.format(start)} – ${timeFmt.format(end)} UTC`; } function getScheduledDate(booking: ThreeHourSchedulable): Date { const raw = booking.scheduledDate ?? booking.preferredDepartureDate; if (!raw) return new Date(0); return new Date(raw); } function toPriorityRow(booking: ThreeHourSchedulable) { return { isGovernment: booking.isGovernment, priorityScore: booking.priorityScore, scheduledDate: booking.scheduledDate ?? booking.preferredDepartureDate ?? "", }; } export function groupBookingsByThreeHourWindow( bookings: T[], ): ThreeHourBookingBucket[] { const map = new Map>(); for (const booking of bookings) { const scheduled = getScheduledDate(booking); const start = bucketStart(scheduled); const end = new Date(start); end.setUTCHours(end.getUTCHours() + 3); const key = start.toISOString(); const existing = map.get(key); if (existing) { existing.bookings.push(booking); } else { map.set(key, { key, label: formatBucketLabel(start, end), start, end, bookings: [booking], }); } } return [...map.values()] .map((bucket) => ({ ...bucket, bookings: [...bucket.bookings].sort((a, b) => compareSchedulingPriority(toPriorityRow(a), toPriorityRow(b)), ), })) .sort((a, b) => a.start.getTime() - b.start.getTime()); }