import { BaseEntity } from '@edr/api-common';
import { Column, Entity, Index, JoinColumn, ManyToOne } from 'typeorm';

import { Booking } from '../../bookings/entities/booking.entity';
import { TrainSchedule } from '../../train-schedules/entities/train-schedule.entity';

export const BOOKING_BATCH_OFFER_STATUSES = ['OFFERED', 'APPLIED', 'EXPIRED'] as const;
export type BookingBatchOfferStatus = (typeof BOOKING_BATCH_OFFER_STATUSES)[number];

/** One reduced container line of a partial offer (per original booking_container row). */
export interface OfferedLine {
  bookingContainerId: string;
  /** Units of this line that ride the offered train (≤ original quantity). */
  quantity: number;
  wagonsRequired: number;
  totalVgmTons: number;
}

/**
 * A partial-capacity payment offer made by the batch when a booking needs more
 * wagons than the train has left (e.g. needs 20, 3 free). The booking itself is
 * NOT mutated at offer time — paying inside the window accepts the split
 * (BookingSplitService.applySplit reduces the booking to the offered lines and
 * the remainder returns to the contract's quantity cap); letting the deadline
 * pass expires the offer and the booking stays whole.
 */
@Entity({ schema: 'freight', name: 'booking_batch_offers' })
@Index(['bookingId'])
@Index(['trainScheduleId'])
@Index(['status'])
export class BookingBatchOffer extends BaseEntity {
  @Column({ name: 'booking_id', type: 'uuid' })
  bookingId!: string;

  @ManyToOne(() => Booking, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'booking_id' })
  booking?: Booking;

  @Column({ name: 'train_schedule_id', type: 'uuid' })
  trainScheduleId!: string;

  @ManyToOne(() => TrainSchedule, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'train_schedule_id' })
  trainSchedule?: TrainSchedule;

  @Column({ name: 'offered_wagons', type: 'int' })
  offeredWagons!: number;

  /** Booking's full wagon need at offer time (for messaging / audit). */
  @Column({ name: 'total_wagons', type: 'int' })
  totalWagons!: number;

  /** Reduced container lines (null for bulk offers — bulk splits by weight). */
  @Column({ name: 'offered_lines', type: 'jsonb', nullable: true })
  offeredLines?: OfferedLine[] | null;

  @Column({ name: 'offered_weight_tons', type: 'numeric', precision: 12, scale: 3 })
  offeredWeightTons!: number;

  @Column({ name: 'offered_amount', type: 'numeric', precision: 14, scale: 2 })
  offeredAmount!: number;

  @Column({ name: 'offered_pricing_breakdown', type: 'jsonb', nullable: true })
  offeredPricingBreakdown?: Record<string, unknown> | null;

  /** The partial PREPAID invoice generated for the offered part. */
  @Column({ name: 'invoice_id', type: 'uuid', nullable: true })
  invoiceId?: string | null;

  @Column({ name: 'payment_deadline', type: 'timestamptz' })
  paymentDeadline!: Date;

  @Column({ name: 'status', type: 'varchar', length: 10, default: 'OFFERED' })
  status!: BookingBatchOfferStatus;
}
