import type { Freight } from "@edr/types";

/**
 * `GET /api/bookings/:id` serializes the raw TypeORM `Booking` entity with its
 * relations attached (company, bookingContainers → units, shippingLine,
 * cargoType…). That's a strict superset of the `Freight.IBooking` DTO, which
 * doesn't declare these relations (and still lists a couple of fields —
 * `freightSubtype`, the string-enum `serviceType` — that the API never
 * actually sends). This augments the shared type with what the endpoint
 * really returns so the detail page can render it without unsafe casts.
 */

export interface BookingContainerUnitDetail {
  id: string;
  containerNumber: string;
  sealNumber?: string | null;
  vgmTons: number | string;
  isHazardous?: boolean;
  isReefer?: boolean;
  isReturn?: boolean;
  receivedToPort?: boolean;
  receivedAt?: string | null;
  grnNumber?: string | null;
  sortOrder?: number;
}

export interface BookingContainerLineDetail {
  id: string;
  quantity: number;
  vgmPerUnitTons: number | string;
  totalVgmTons: number | string;
  hazardousQuantity?: number;
  reeferQuantity?: number;
  returnQuantity?: number;
  isOverweight?: boolean;
  overweightExcessTons?: number | string | null;
  containerNumber?: string | null;
  containerType?: {
    code: string;
    label?: string | null;
    sizeFt?: number | null;
    isReefer?: boolean | null;
  } | null;
  units?: BookingContainerUnitDetail[];
}

export interface BookingShippingLineDetail {
  code: string;
  label: string;
  showExtraFeeNotice?: boolean;
}

export interface BookingCargoTypeDetail {
  code: string;
  cargoTypeName: string;
  unitOfMeasure?: string | null;
}

/** The API's real (object) shape for the joined service-type relation. */
export type BookingServiceTypeRef = NonNullable<Freight.IContract["serviceType"]>;

export type BookingDetail = Freight.IBooking & {
  /** Billed-to company relation, always joined on the detail endpoint. */
  company?: Freight.BookingRequestCompany | null;
  isGovernment?: boolean;
  governmentInstitution?: string | null;
  /** Real container line-items (with per-unit numbers/seals/VGM). */
  bookingContainers?: BookingContainerLineDetail[] | null;
  shippingLine?: BookingShippingLineDetail | null;
  cargoType?: BookingCargoTypeDetail | null;
  cargoFreeText?: string | null;
  /** Joined paired-booking relation (consolidation partner), not just its id. */
  consolidationPartner?: {
    id: string;
    reference: string;
    status: string;
  } | null;
};

/**
 * `booking.serviceType` is declared as the legacy `"RAIL_ONLY" |
 * "RAIL_AND_FORWARDING"` string enum on `Freight.IBooking`, but the API
 * actually sends the joined ServiceType relation object (`{ code,
 * serviceName, includesFirstMile, includesLastMile, includesCustoms, … }`).
 * Read it through this helper instead of comparing directly — see
 * `serviceTypeLabel()` in `utils.ts`.
 */
export function rawServiceType(
  booking: BookingDetail,
): string | BookingServiceTypeRef | null | undefined {
  return (booking as unknown as { serviceType?: string | BookingServiceTypeRef | null })
    .serviceType;
}
