import { api as client } from '../auth/http'; import { unwrap } from '@/utils/endpoint'; import { URL_CONSTANTS } from '@/constants/URLS'; import type { AssignBookingsPayload, CreateTrainSchedulePayload, EligibleContainerBookingsResponse, FreightType, LocomotiveRecord, PinWagonsPayload, TrainScheduleDetail, TrainScheduleFilters, TrainScheduleListItem, TrainSchedulePreviewPayload, TrainSchedulePreviewResponse, TrainSchedulingGlobalRules, YardOption, } from '@/types/trainScheduling'; interface BookingReferenceDataResponse { yard?: Array; } const pathsFor = (freightType?: FreightType) => freightType === "BULK" ? URL_CONSTANTS.TRAIN_SCHEDULING.BULK : URL_CONSTANTS.TRAIN_SCHEDULING.CONTAINER; export const trainSchedulingService = { getEligibleBookings: async ( filters?: TrainScheduleFilters, freightType?: FreightType, ): Promise => { const useUnified = !freightType || freightType === "MIXED"; // The container/bulk endpoints already encode freight type in the path, and their // query DTOs reject an extra `freightType` param — so only pass the station filters. const response = await client.get( useUnified ? URL_CONSTANTS.TRAIN_SCHEDULING.ELIGIBLE_BOOKINGS : pathsFor(freightType).ELIGIBLE_BOOKINGS, { params: { ...filters } }, ); return unwrap(response.data); }, preview: async ( payload: TrainSchedulePreviewPayload, freightType?: FreightType, ): Promise => { const useUnified = !freightType || freightType === "MIXED"; const response = await client.post( useUnified ? URL_CONSTANTS.TRAIN_SCHEDULING.PREVIEW : pathsFor(freightType).PREVIEW, payload, ); return unwrap(response.data); }, createSchedule: async ( payload: CreateTrainSchedulePayload, freightType?: FreightType, ): Promise => { const response = await client.post( pathsFor(freightType).SCHEDULES, payload, ); return unwrap(response.data); }, listSchedules: async ( freightType: FreightType = "CONTAINER", ): Promise => { const response = await client.get( pathsFor(freightType === "MIXED" ? undefined : freightType).SCHEDULES, ); return unwrap(response.data); }, getScheduleById: async ( id: string, freightType?: FreightType, ): Promise => { const response = await client.get( pathsFor(freightType === "MIXED" ? undefined : freightType).SCHEDULE_BY_ID(id), ); return unwrap(response.data); }, assignBookings: async ( scheduleId: string, payload: AssignBookingsPayload, freightType?: FreightType, ): Promise => { const useUnified = !freightType || freightType === "MIXED"; const response = await client.post( useUnified ? URL_CONSTANTS.TRAIN_SCHEDULING.ASSIGN_BOOKINGS(scheduleId) : pathsFor(freightType).ASSIGN_BOOKINGS(scheduleId), payload, ); return unwrap(response.data); }, unassignBooking: async ( scheduleId: string, bookingId: string, ): Promise => { const response = await client.delete( URL_CONSTANTS.TRAIN_SCHEDULING.UNASSIGN_BOOKING(scheduleId, bookingId), ); return unwrap(response.data); }, pinWagons: async ( scheduleId: string, payload: PinWagonsPayload, ): Promise => { const response = await client.post( URL_CONSTANTS.TRAIN_SCHEDULING.PIN_WAGONS(scheduleId), payload, ); return unwrap(response.data); }, finalizeSchedule: async (scheduleId: string): Promise => { const response = await client.post( URL_CONSTANTS.TRAIN_SCHEDULING.FINALIZE(scheduleId), {}, ); return unwrap(response.data); }, dispatchSchedule: async (scheduleId: string): Promise => { const response = await client.post( URL_CONSTANTS.TRAIN_SCHEDULING.DISPATCH(scheduleId), {}, ); return unwrap(response.data); }, cancelSchedule: async ( id: string, freightType: FreightType = "CONTAINER", ): Promise => { const response = await client.post( pathsFor(freightType === "MIXED" ? undefined : freightType).CANCEL_SCHEDULE(id), {}, ); return unwrap(response.data); }, getAvailableLocomotives: async (): Promise => { const response = await client.get(URL_CONSTANTS.LOCOMOTIVES.BASE, { params: { status: 'AVAILABLE' }, }); return unwrap(response.data); }, previewReschedule: async ( scheduleId: string, payload: { incomingBookingIds: string[]; trigger: string; reason?: string; newDepartureDate?: string; }, ) => { const response = await client.post( URL_CONSTANTS.TRAIN_SCHEDULING.RESCHEDULE_PREVIEW(scheduleId), payload, ); return unwrap(response.data); }, executeReschedule: async ( scheduleId: string, payload: { incomingBookingIds: string[]; trigger: string; reason?: string; newDepartureDate?: string; finalBookingIds: string[]; displacedBookingIds: string[]; }, ) => { const response = await client.post( URL_CONSTANTS.TRAIN_SCHEDULING.RESCHEDULE_EXECUTE(scheduleId), payload, ); return unwrap(response.data); }, maintenanceReschedule: async ( scheduleId: string, payload: { incomingBookingIds: string[]; newDepartureDate: string; reason?: string; }, ) => { const response = await client.post( URL_CONSTANTS.TRAIN_SCHEDULING.MAINTENANCE(scheduleId), { ...payload, trigger: "TRAIN_MAINTENANCE" }, ); return unwrap(response.data); }, getGlobalRules: async (): Promise => { const response = await client.get( URL_CONSTANTS.TRAIN_SCHEDULING.GLOBAL_RULES, ); return unwrap(response.data); }, updateGlobalRules: async ( payload: Partial< Pick< TrainSchedulingGlobalRules, | "maxTrainLengthMeters" | "maxTrainWeightTons" | "maxWagonsPerTrain" | "max20ftContainerWeightTons" | "max20ftPairWeightDiffTons" > >, ): Promise => { const response = await client.patch( URL_CONSTANTS.TRAIN_SCHEDULING.GLOBAL_RULES, payload, ); return unwrap(response.data); }, getStations: async (): Promise => { const response = await client.get( URL_CONSTANTS.BOOKINGS.REFERENCE_DATA, ); const data = unwrap(response.data); return (data.yard ?? []).map((yard) => ({ id: yard.id, name: yard.name ?? yard.label ?? yard.code, code: yard.code, country: yard.country, })); }, };