import { BadRequestException } from '@nestjs/common';
import type { DataSource, EntityManager } from 'typeorm';

/** The booking fields the gate needs. */
export interface ExportLoadGateBooking {
  id: string;
  tradeDirection?: string | null;
}

/**
 * Export cargo may not be loaded onto its train until it has physically reached
 * the warehouse and been issued a GRN — whether it got there by first-mile or by
 * the customer's own truck, and even though a wagon is already allocated. An
 * allocation is a plan; the GRN is the proof the goods are actually in hand.
 *
 * Several loading paths (per-yard load, workspace confirm-loaded) marked cargo
 * loaded straight off the allocation, skipping the warehouse, so a booking could
 * ride the train with nothing ever received. This closes that for export; import
 * loads off a train and is unaffected.
 *
 * "Received with a GRN" = an inventory row that has reached the warehouse
 * (RECEIVED or any later stage) and carries a GRN, in the column or the notes
 * fallback older rows use.
 */
export async function assertExportReceivedWithGrn(
  db: DataSource | EntityManager,
  booking: ExportLoadGateBooking,
): Promise<void> {
  if (booking.tradeDirection !== 'EXPORT') return;

  const [row] = await db.query(
    `SELECT 1
       FROM freight.warehouse_inventory inv
      WHERE inv.booking_id = $1
        AND inv.deleted_at IS NULL
        AND inv.status IN ('RECEIVED', 'STORED', 'RESERVED', 'READY_FOR_LOADING', 'LOADED', 'DISPATCHED')
        AND COALESCE(
              NULLIF(TRIM(inv.grn_number), ''),
              substring(inv.notes FROM 'GRN Number: ([^\\n\\r]+)')
            ) IS NOT NULL
      LIMIT 1`,
    [booking.id],
  );

  if (!row) {
    throw new BadRequestException(
      'This export booking has not been received at the warehouse yet — receive its cargo and generate a GRN before loading it onto the train.',
    );
  }
}
