/**
 * Fixed train-number pools assigned to a train on dispatch.
 *
 * The prefix encodes cargo type (8 = container, 1 = bulk) and the parity encodes
 * trade direction (odd = export, even = import). Numbers are finite and recycle:
 * a number is "in use" only while its train is DISPATCHED and not yet ARRIVED.
 */

export const CONTAINER_EXPORT_NUMBERS = [
  '8001', '8101', '8201', '8301', '8401', '8501', '8601', '8701', '8801', '8901',
] as const;

export const CONTAINER_IMPORT_NUMBERS = [
  '8002', '8102', '8202', '8302', '8402', '8502', '8602', '8702', '8802', '8902',
] as const;

export const BULK_EXPORT_NUMBERS = ['1101', '1103', '1105', '1107'] as const;

export const BULK_IMPORT_NUMBERS = ['1002', '1004', '1006', '1008'] as const;

export type CargoKind = 'CONTAINER' | 'BULK';
export type PoolDirection = 'IMPORT' | 'EXPORT';

export interface TrainNumberPool {
  cargo: CargoKind;
  /** EXPORT = odd numbers, IMPORT = even numbers. */
  direction: PoolDirection;
  numbers: readonly string[];
}

/**
 * Resolve which fixed pool a train draws from.
 *
 * - Cargo: container vs bulk by dominant wagon count; ties resolve to container.
 * - Direction: EXPORT → odd pool, IMPORT → even pool. DOMESTIC (neither end is
 *   Djibouti) has no dedicated pool, so it defaults to the export/odd pool.
 */
export function pickTrainNumberPool(
  containerWagons: number,
  bulkWagons: number,
  direction: 'IMPORT' | 'EXPORT' | 'DOMESTIC' | null | undefined,
): TrainNumberPool {
  const cargo: CargoKind = bulkWagons > containerWagons ? 'BULK' : 'CONTAINER';
  const poolDirection: PoolDirection = direction === 'IMPORT' ? 'IMPORT' : 'EXPORT';

  const numbers =
    cargo === 'CONTAINER'
      ? poolDirection === 'IMPORT'
        ? CONTAINER_IMPORT_NUMBERS
        : CONTAINER_EXPORT_NUMBERS
      : poolDirection === 'IMPORT'
        ? BULK_IMPORT_NUMBERS
        : BULK_EXPORT_NUMBERS;

  return { cargo, direction: poolDirection, numbers };
}

/** Lowest pool number not currently in use, or null when the pool is exhausted. */
export function pickLowestFreeNumber(
  pool: readonly string[],
  usedNumbers: Iterable<string>,
): string | null {
  const used = new Set(usedNumbers);
  for (const number of pool) {
    if (!used.has(number)) return number;
  }
  return null;
}
