import 'reflect-metadata';
import { config } from 'dotenv';
import { resolve } from 'path';
import { WagonStatus } from '@edr/types';
import { In } from 'typeorm';

config({ path: resolve(__dirname, '../../.env') });

import { AppDataSource } from '../data-source';
import { BookingContainer } from '../modules/bookings/entities/booking-container.entity';
import { Booking } from '../modules/bookings/entities/booking.entity';
import { CompanyProfile, ProfileStatus, ProfileType } from '../modules/companies/entities/company-profile.entity';
import { Company, CompanyKind, CompanyStatus, CompanyType } from '../modules/companies/entities/company.entity';
import { Container } from '../modules/container-management/entities/container.entity';
import { Locomotive } from '../modules/locomotives/entities/locomotive.entity';
import { ContainerType } from '../modules/rule-engine/entities/container-type.entity';
import { ServiceType } from '../modules/rule-engine/entities/service-type.entity';
import { Yard } from '../modules/rule-engine/entities/yard.entity';
import { ImportDjiboutiOperation } from '../modules/train-scheduling/entities/import-djibouti-operation.entity';
import { TrainScheduleBooking } from '../modules/train-schedules/entities/train-schedule-booking.entity';
import { WagonAllocationContainerItem } from '../modules/train-schedules/entities/wagon-allocation-container-item.entity';
import { WagonBookingAllocation } from '../modules/train-schedules/entities/wagon-booking-allocation.entity';
import { TrainSchedule } from '../modules/train-schedules/entities/train-schedule.entity';
import { TrainSetWagon } from '../modules/train-sets/entities/train-set-wagon.entity';
import { TrainSet } from '../modules/train-sets/entities/train-set.entity';
import { WagonType } from '../modules/wagon-types/entities/wagon-type.entity';
import { Wagon } from '../modules/wagons/entities/wagon.entity';
import { WarehouseInventory } from '../modules/warehouses/entities/warehouse-inventory.entity';
import { WarehouseYard } from '../modules/warehouses/entities/warehouse-yard.entity';
import { WarehouseZone } from '../modules/warehouses/entities/warehouse-zone.entity';
import { Warehouse } from '../modules/warehouses/entities/warehouse.entity';

type Direction = 'IMPORT' | 'EXPORT';
type TrainStatus = 'SCHEDULED' | 'ARRIVED';

interface ScenarioTrain {
  trainNumber: string;
  direction: Direction;
  status: TrainStatus;
  departureOffsetHours: number;
  arrivalOffsetHours: number;
  bookings: Array<{
    reference: string;
    mileVariant: 'FIRST_MILE' | 'LAST_MILE' | 'TERMINAL';
    containerNumber: string;
    weightTons: number;
  }>;
}

const SCENARIOS: ScenarioTrain[] = [
  {
    trainNumber: 'GP-IMP-ARR-01',
    direction: 'IMPORT',
    status: 'ARRIVED',
    departureOffsetHours: -18,
    arrivalOffsetHours: -6,
    bookings: [
      { reference: 'GP-IMP-ARR-LM-001', mileVariant: 'LAST_MILE', containerNumber: 'GPIM0000001', weightTons: 22 },
      { reference: 'GP-IMP-ARR-TM-002', mileVariant: 'TERMINAL', containerNumber: 'GPIM0000002', weightTons: 24 },
    ],
  },
  {
    trainNumber: 'GP-IMP-NARR-01',
    direction: 'IMPORT',
    status: 'SCHEDULED',
    departureOffsetHours: 6,
    arrivalOffsetHours: 18,
    bookings: [
      { reference: 'GP-IMP-NARR-LM-001', mileVariant: 'LAST_MILE', containerNumber: 'GPIM0000003', weightTons: 21 },
      { reference: 'GP-IMP-NARR-TM-002', mileVariant: 'TERMINAL', containerNumber: 'GPIM0000004', weightTons: 23 },
    ],
  },
  {
    trainNumber: 'GP-EXP-ARR-01',
    direction: 'EXPORT',
    status: 'ARRIVED',
    departureOffsetHours: -16,
    arrivalOffsetHours: -4,
    bookings: [
      { reference: 'GP-EXP-ARR-FM-001', mileVariant: 'FIRST_MILE', containerNumber: 'GPEX0000001', weightTons: 20 },
      { reference: 'GP-EXP-ARR-TM-002', mileVariant: 'TERMINAL', containerNumber: 'GPEX0000002', weightTons: 22 },
    ],
  },
  {
    trainNumber: 'GP-EXP-NARR-01',
    direction: 'EXPORT',
    status: 'SCHEDULED',
    departureOffsetHours: 8,
    arrivalOffsetHours: 20,
    bookings: [
      { reference: 'GP-EXP-NARR-FM-001', mileVariant: 'FIRST_MILE', containerNumber: 'GPEX0000003', weightTons: 19 },
      { reference: 'GP-EXP-NARR-TM-002', mileVariant: 'TERMINAL', containerNumber: 'GPEX0000004', weightTons: 21 },
    ],
  },
];

const addHours = (date: Date, hours: number): Date => new Date(date.getTime() + hours * 60 * 60 * 1000);

async function main() {
  const dataSource = await AppDataSource.initialize();

  try {
    const seeded = await dataSource.transaction(async (manager) => {
      if (await isAlreadySeeded(manager)) {
        return null;
      }
      const refs = await ensureReferences(manager);
      const now = new Date();
      const result: Array<{ trainNumber: string; bookings: string[] }> = [];

      for (const scenario of SCENARIOS) {
        const schedule = await seedScenarioTrain(manager, scenario, refs, now);
        result.push({
          trainNumber: schedule.trainNumber ?? scenario.trainNumber,
          bookings: scenario.bookings.map((booking) => booking.reference),
        });
      }

      return result;
    });

    console.log('Gate-pass train scenario seed complete.');
    if (seeded) {
      for (const row of seeded) {
        console.log(`${row.trainNumber}: ${row.bookings.join(', ')}`);
      }
    } else {
      console.log('Gate-pass train scenarios already seeded; nothing changed.');
    }
  } finally {
    await dataSource.destroy();
  }
}

async function isAlreadySeeded(manager: any): Promise<boolean> {
  const scheduleRepo = manager.getRepository(TrainSchedule);
  const bookingRepo = manager.getRepository(Booking);
  const trainNumbers = SCENARIOS.map((scenario) => scenario.trainNumber);
  const bookingRefs = SCENARIOS.flatMap((scenario) => scenario.bookings.map((booking) => booking.reference));

  const [scheduleCount, bookingCount] = await Promise.all([
    scheduleRepo.count({ where: { trainNumber: In(trainNumbers) } }),
    bookingRepo.count({ where: { reference: In(bookingRefs) } }),
  ]);

  return scheduleCount === trainNumbers.length && bookingCount === bookingRefs.length;
}

async function ensureReferences(manager: any) {
  const yardRepo = manager.getRepository(Yard);
  const serviceTypeRepo = manager.getRepository(ServiceType);
  const containerTypeRepo = manager.getRepository(ContainerType);
  const wagonTypeRepo = manager.getRepository(WagonType);
  const companyRepo = manager.getRepository(Company);
  const profileRepo = manager.getRepository(CompanyProfile);
  const warehouseRepo = manager.getRepository(Warehouse);
  const warehouseYardRepo = manager.getRepository(WarehouseYard);
  const warehouseZoneRepo = manager.getRepository(WarehouseZone);

  const djiboutiYard =
    (await yardRepo.findOne({ where: { code: 'NAGAD' } })) ??
    (await yardRepo.findOne({ where: { code: 'DJIB_PORT' } })) ??
    (await yardRepo.findOne({ where: { country: 'Djibouti' } })) ??
    (await yardRepo.save(
      yardRepo.create({
        code: 'NAGAD',
        label: 'Nagad Port',
        country: 'Djibouti',
        isActive: true,
        displayOrder: 90,
      }),
    ));

  const ethiopiaYard =
    (await yardRepo.findOne({ where: { code: 'INDODE' } })) ??
    (await yardRepo.findOne({ where: { code: 'MOJO' } })) ??
    (await yardRepo.findOne({ where: { country: 'Ethiopia' } })) ??
    (await yardRepo.save(
      yardRepo.create({
        code: 'INDODE',
        label: 'Indode Dry Port',
        country: 'Ethiopia',
        isActive: true,
        displayOrder: 91,
      }),
    ));

  const serviceType =
    (await serviceTypeRepo.findOne({ where: { code: 'RAIL_CONTAINER' } })) ??
    (await serviceTypeRepo.save(
      serviceTypeRepo.create({
        code: 'RAIL_CONTAINER',
        serviceName: 'Rail Container Service',
        description: 'Rail container service for gate-pass scenario seed',
        canBeBookedAlone: true,
        includesFirstMile: false,
        includesLastMile: false,
        includesCustoms: false,
        isActive: true,
        displayOrder: 1,
      }),
    ));

  const containerType =
    (await containerTypeRepo.findOne({ where: { code: '40FT' } })) ??
    (await containerTypeRepo.findOne({ where: { isActive: true } })) ??
    (await containerTypeRepo.save(
      containerTypeRepo.create({
        code: '40FT',
        label: '40FT',
        sizeFt: 40,
        isReefer: false,
        isOpenTop: false,
        isActive: true,
        displayOrder: 1,
      }),
    ));

  const wagonType =
    (await wagonTypeRepo.findOne({ where: { code: 'GP-FLAT' } })) ??
    (await wagonTypeRepo.findOne({ where: { supportsContainer: true } })) ??
    (await wagonTypeRepo.findOne({ where: { isActive: true } })) ??
    (await wagonTypeRepo.save(
      wagonTypeRepo.create({
        code: 'GP-FLAT',
        name: 'Gate Pass Demo Flat Wagon',
        capacityTons: 70,
        lengthMeters: 14,
        supportedLoadTypes: ['CONTAINER'],
        isActive: true,
        equatedLengthM: 14,
        tareWeightTons: 20,
        supportsContainer: true,
        maxContainerGrossT: 70,
      }),
    ));

  const company =
    (await companyRepo.findOne({ where: { tin: 'GTPASS001' } })) ??
    (await companyRepo.save(
      companyRepo.create({
        name: 'Gate Pass Scenario Customer',
        type: CompanyType.Customer,
        kind: CompanyKind.Commercial,
        status: CompanyStatus.Active,
        tin: 'GTPASS001',
        vatNumber: 'GTPASS001',
        fanNumber: 'GTPASS0000001',
        country: 'Ethiopia',
        address: 'Indode Dry Port',
        phone: '251900000555',
        email: 'gate-pass-scenarios@edr.local',
        contactPersonName: 'Gate Pass Tester',
        contactPersonPhone: '251900000555',
      }),
    ));

  const importerProfile = await ensureProfile(profileRepo, company.id, ProfileType.importer, 'GP-IMP');
  const exporterProfile = await ensureProfile(profileRepo, company.id, ProfileType.exporter, 'GP-EXP');

  const warehouse =
    (await warehouseRepo.findOne({ where: { code: 'INDODE_OPEN' } })) ??
    (await warehouseRepo.findOne({ where: {} }));
  if (!warehouse) {
    throw new Error('No warehouse found. Run the Indode/warehouse seed before gate-pass scenarios.');
  }
  const warehouseYard = await warehouseYardRepo.findOne({ where: { warehouseId: warehouse.id } });
  if (!warehouseYard) {
    throw new Error(`No warehouse yard found for ${warehouse.code ?? warehouse.id}.`);
  }
  const warehouseZone = await warehouseZoneRepo.findOne({ where: { yardId: warehouseYard.id } });
  if (!warehouseZone) {
    throw new Error(`No warehouse zone found for yard ${warehouseYard.id}.`);
  }

  return {
    djiboutiYard,
    ethiopiaYard,
    serviceType,
    containerType,
    wagonType,
    company,
    importerProfile,
    exporterProfile,
    warehouse,
    warehouseYard,
    warehouseZone,
  };
}

async function ensureProfile(repo: any, companyId: string, type: ProfileType, reference: string): Promise<CompanyProfile> {
  const existing = await repo.findOne({ where: { companyId, type } });
  if (existing) return existing;
  return repo.save(
    repo.create({
      companyId,
      type,
      reference,
      status: ProfileStatus.Active,
      businessLicense: `${reference}-LICENSE`,
    }),
  );
}

async function seedScenarioTrain(manager: any, scenario: ScenarioTrain, refs: Awaited<ReturnType<typeof ensureReferences>>, now: Date) {
  const locomotiveRepo = manager.getRepository(Locomotive);
  const trainSetRepo = manager.getRepository(TrainSet);
  const scheduleRepo = manager.getRepository(TrainSchedule);
  const trainSetWagonRepo = manager.getRepository(TrainSetWagon);
  const wagonRepo = manager.getRepository(Wagon);

  const departure = addHours(now, scenario.departureOffsetHours);
  const arrival = addHours(now, scenario.arrivalOffsetHours);
  const isArrived = scenario.status === 'ARRIVED';
  const originYard = scenario.direction === 'IMPORT' ? refs.djiboutiYard : refs.ethiopiaYard;
  const destinationYard = scenario.direction === 'IMPORT' ? refs.ethiopiaYard : refs.djiboutiYard;
  const totalWeightTons = scenario.bookings.reduce((sum, booking) => sum + booking.weightTons, 0);

  const locomotive =
    (await locomotiveRepo.findOne({ where: { code: 'GP-DEMO-LOCO' } })) ??
    (await locomotiveRepo.save(
      locomotiveRepo.create({
        code: 'GP-DEMO-LOCO',
        name: 'Gate Pass Scenario Locomotive',
        locomotiveType: 'DIESEL',
        maxPullWeightTons: 4200,
        maxTrainLengthMeters: 760,
        status: 'AVAILABLE',
        currentYardId: originYard.id,
      }),
    ));

  let schedule = await scheduleRepo.findOne({ where: { trainNumber: scenario.trainNumber } });
  let trainSet: TrainSet | null = schedule?.trainSetId
    ? await trainSetRepo.findOne({ where: { id: schedule.trainSetId } })
    : null;

  if (!trainSet) {
    trainSet = await trainSetRepo.save(
      trainSetRepo.create({
        locomotiveId: locomotive.id,
        totalWeightTons,
        totalLengthMeters: scenario.bookings.length * 14,
        wagonCount: scenario.bookings.length,
        status: isArrived ? 'COMPLETED' : 'ASSIGNED',
      }),
    );
  } else {
    await trainSetRepo.update(trainSet.id, {
      locomotiveId: locomotive.id,
      totalWeightTons,
      totalLengthMeters: scenario.bookings.length * 14,
      wagonCount: scenario.bookings.length,
      status: isArrived ? 'COMPLETED' : 'ASSIGNED',
    });
  }
  if (!trainSet) {
    throw new Error(`Could not create train set for ${scenario.trainNumber}`);
  }
  const trainSetId = trainSet.id;

  if (!schedule) {
    schedule = scheduleRepo.create({ trainNumber: scenario.trainNumber });
  }
  Object.assign(schedule, {
    trainSetId,
    originStationId: originYard.id,
    destinationStationId: destinationYard.id,
    scheduledDepartureDate: departure,
    scheduledArrivalDate: arrival,
    actualDepartureAt: isArrived ? departure : null,
    actualArrivalAt: isArrived ? arrival : null,
    status: scenario.status,
    direction: scenario.direction,
    maxWagons: 53,
    bookingWindowStatus: 'CLOSED',
  });
  schedule = await scheduleRepo.save(schedule);

  for (const [index, bookingSpec] of scenario.bookings.entries()) {
    const sequenceNo = index + 1;
    const wagon = await ensureWagon(manager, scenario, sequenceNo, refs.wagonType.id, originYard.id, schedule.id);
    const trainSetWagon = await ensureTrainSetWagon(
      trainSetWagonRepo,
      trainSetId,
      refs.wagonType.id,
      wagon.id,
      sequenceNo,
      bookingSpec.weightTons,
      isArrived,
    );
    await wagonRepo.update(wagon.id, { trainSetWagonId: trainSetWagon.id });

    const booking = await ensureBooking(manager, scenario, bookingSpec, refs, departure, now, schedule.id);
    const bookingContainer = await ensureBookingContainer(manager, booking.id, refs.containerType.id, bookingSpec);
    const allocation = await ensureAllocation(manager, trainSetWagon.id, booking.id, bookingSpec.weightTons, isArrived, now);
    const container = await ensureContainer(manager, booking.id, bookingContainer.id, allocation.id, wagon.id, sequenceNo, bookingSpec, refs.containerType.id, isArrived);
    await ensureContainerItem(manager, allocation.id, bookingContainer.id, container.id, refs.containerType.id, sequenceNo, bookingSpec);
    await ensureScheduleBooking(manager, schedule.id, booking.id);
    if (scenario.direction === 'EXPORT') {
      await ensureExportInventory(manager, refs, booking.id, container.id, bookingSpec.weightTons, isArrived, now);
    }
  }

  if (scenario.direction === 'IMPORT') {
    await ensureImportOperation(manager, schedule.id, scenario, departure, isArrived);
  }

  return schedule;
}

async function ensureWagon(manager: any, scenario: ScenarioTrain, sequenceNo: number, wagonTypeId: string, yardId: string, scheduleId: string): Promise<Wagon> {
  const repo = manager.getRepository(Wagon);
  const wagonNumber = `${scenario.trainNumber}-W${String(sequenceNo).padStart(2, '0')}`;
  const existing = await repo.findOne({ where: { wagonNumber } });
  const values = {
    wagonNumber,
    wagonTypeId,
    trainId: null,
    sequenceNumber: sequenceNo,
    status: WagonStatus.Assigned,
    currentYardId: yardId,
    currentTrainScheduleId: scheduleId,
    notes: 'Gate-pass scenario seed wagon',
  };
  return repo.save(repo.create({ ...(existing ?? {}), ...values }));
}

async function ensureTrainSetWagon(repo: any, trainSetId: string, wagonTypeId: string, wagonId: string, sequenceNo: number, weightTons: number, isArrived: boolean): Promise<TrainSetWagon> {
  const existing = await repo.findOne({ where: { trainSetId, sequenceNo } });
  return repo.save(
    repo.create({
      ...(existing ?? {}),
      trainSetId,
      wagonTypeId,
      physicalWagonId: wagonId,
      sequenceNo,
      capacityTons: 70,
      lengthMeters: 14,
      assignedWeightTons: weightTons,
      status: isArrived ? 'DEPARTED' : 'LOADED',
    }),
  );
}

async function ensureBooking(manager: any, scenario: ScenarioTrain, bookingSpec: ScenarioTrain['bookings'][number], refs: Awaited<ReturnType<typeof ensureReferences>>, departure: Date, now: Date, scheduleId: string): Promise<Booking> {
  const repo = manager.getRepository(Booking);
  const originYard = scenario.direction === 'IMPORT' ? refs.djiboutiYard : refs.ethiopiaYard;
  const destinationYard = scenario.direction === 'IMPORT' ? refs.ethiopiaYard : refs.djiboutiYard;
  const existing = await repo.findOne({ where: { reference: bookingSpec.reference } });
  const profile = scenario.direction === 'IMPORT' ? refs.importerProfile : refs.exporterProfile;
  const hasFirstMile = bookingSpec.mileVariant === 'FIRST_MILE';
  const hasLastMile = bookingSpec.mileVariant === 'LAST_MILE';

  return repo.save(
    repo.create({
      ...(existing ?? {}),
      reference: bookingSpec.reference,
      companyId: refs.company.id,
      companyProfileId: profile.id,
      originYardId: originYard.id,
      destinationYardId: destinationYard.id,
      serviceTypeId: refs.serviceType.id,
      status: scenario.status === 'ARRIVED' ? 'IN_TRANSIT' : 'PAID',
      paymentStatus: 'PAID',
      scheduledDate: departure,
      estimatedShipmentDate: departure,
      contractType: 'SPOT',
      equipmentReturn: 'TERMINAL',
      paymentCurrency: 'ETB',
      totalAmount: 0,
      isGovernment: false,
      tradeDirection: scenario.direction,
      freightType: 'CONTAINER',
      cargoTypeId: null,
      cargoFreeText: `${scenario.direction} gate-pass scenario ${bookingSpec.mileVariant.toLowerCase().replace('_', ' ')}`,
      cargoTotalWeightVgm: bookingSpec.weightTons * 1000,
      firstMilePickupAddress: hasFirstMile ? 'Customer factory pickup - Addis Ababa' : null,
      firstMilePickupLat: hasFirstMile ? 9.03 : null,
      firstMilePickupLng: hasFirstMile ? 38.74 : null,
      lastMileDeliveryAddress: hasLastMile ? 'Customer warehouse delivery - Addis Ababa' : null,
      lastMileDeliveryLat: hasLastMile ? 8.98 : null,
      lastMileDeliveryLng: hasLastMile ? 38.8 : null,
      trainScheduleId: scheduleId,
      schedulingStatus: scenario.status === 'ARRIVED' ? 'DISPATCHED' : 'SCHEDULED',
      scheduledAt: now,
      wagonsRequired: 1,
    }),
  );
}

async function ensureBookingContainer(manager: any, bookingId: string, containerTypeId: string, bookingSpec: ScenarioTrain['bookings'][number]): Promise<BookingContainer> {
  const repo = manager.getRepository(BookingContainer);
  const existing = await repo.findOne({ where: { bookingId } });
  return repo.save(
    repo.create({
      ...(existing ?? {}),
      bookingId,
      containerTypeId,
      containerNumber: bookingSpec.containerNumber,
      containerSize: '40',
      quantity: 1,
      hazardousQuantity: 0,
      reeferQuantity: 0,
      vgmPerUnitTons: bookingSpec.weightTons,
      totalVgmTons: bookingSpec.weightTons,
      wagonsRequired: 1,
      weightLimitRuleId: null,
      isOverweight: false,
      overweightExcessTons: null,
    }),
  );
}

async function ensureAllocation(manager: any, trainSetWagonId: string, bookingId: string, weightTons: number, isArrived: boolean, now: Date): Promise<WagonBookingAllocation> {
  const repo = manager.getRepository(WagonBookingAllocation);
  const existing = await repo.findOne({ where: { trainSetWagonId, bookingId } });
  return repo.save(
    repo.create({
      ...(existing ?? {}),
      trainSetWagonId,
      bookingId,
      allocatedWeightTons: weightTons,
      loadType: 'CONTAINER',
      status: isArrived ? 'DEPARTED' : 'LOADED',
      confirmedAt: now,
    }),
  );
}

async function ensureContainer(manager: any, bookingId: string, bookingContainerId: string, allocationId: string, wagonId: string, position: number, bookingSpec: ScenarioTrain['bookings'][number], containerTypeId: string, isArrived: boolean): Promise<Container> {
  const repo = manager.getRepository(Container);
  const existing = await repo.findOne({ where: { containerNumber: bookingSpec.containerNumber } });
  return repo.save(
    repo.create({
      ...(existing ?? {}),
      containerNumber: bookingSpec.containerNumber,
      containerTypeId,
      wagonId,
      position,
      tareWeight: 3800,
      maxGrossWeight: 30480,
      sealNumber: `SEAL-${bookingSpec.containerNumber}`,
      status: isArrived ? 'IN_TRANSIT' : 'LOADED',
      bookingId,
      wagonBookingAllocationId: allocationId,
      bookingContainerId,
    }),
  );
}

async function ensureContainerItem(manager: any, allocationId: string, bookingContainerId: string, containerId: string, containerTypeId: string, position: number, bookingSpec: ScenarioTrain['bookings'][number]): Promise<void> {
  const repo = manager.getRepository(WagonAllocationContainerItem);
  await repo.delete({ wagonBookingAllocationId: allocationId });
  await repo.save(
    repo.create({
      wagonBookingAllocationId: allocationId,
      bookingContainerId,
      containerId,
      containerNumber: bookingSpec.containerNumber,
      containerTypeId,
      positionOnWagon: position,
      sealNumber: `SEAL-${bookingSpec.containerNumber}`,
      chassisNumber: `CHS-${bookingSpec.containerNumber}`,
      grossWeightTons: bookingSpec.weightTons,
    }),
  );
}

async function ensureScheduleBooking(manager: any, scheduleId: string, bookingId: string): Promise<void> {
  const repo = manager.getRepository(TrainScheduleBooking);
  const existing = await repo.findOne({ where: { bookingId } });
  await repo.save(repo.create({ ...(existing ?? {}), trainScheduleId: scheduleId, bookingId }));
}

async function ensureExportInventory(manager: any, refs: Awaited<ReturnType<typeof ensureReferences>>, bookingId: string, containerId: string, weightTons: number, isArrived: boolean, now: Date): Promise<void> {
  const repo = manager.getRepository(WarehouseInventory);
  const existing = await repo.findOne({ where: { bookingId } });
  await repo.save(
    repo.create({
      ...(existing ?? {}),
      warehouseId: refs.warehouse.id,
      yardId: refs.warehouseYard.id,
      zoneId: refs.warehouseZone.id,
      bookingId,
      containerId,
      quantity: 1,
      weight: weightTons * 1000,
      status: 'LOADED',
      inspectionStatus: 'PASSED',
      arrivedAt: addHours(now, -24),
      inspectedAt: addHours(now, -22),
      readyForLoadingAt: addHours(now, -20),
      loadedAt: isArrived ? addHours(now, -16) : null,
      notes: '[GP-SCENARIO] Export train gate-pass scenario inventory',
    }),
  );
}

async function ensureImportOperation(manager: any, scheduleId: string, scenario: ScenarioTrain, departure: Date, isArrived: boolean): Promise<void> {
  const repo = manager.getRepository(ImportDjiboutiOperation);
  const existing = await repo.findOne({ where: { trainScheduleId: scheduleId } });
  await repo.save(
    repo.create({
      ...(existing ?? {}),
      trainScheduleId: scheduleId,
      documents: existing?.documents ?? {},
      gatepassGrantedAt: null,
      readyForLoadingAt: null,
      loadedOnTrainAt: null,
      departedFromDjiboutiAt: isArrived ? departure : null,
      loadListGeneratedAt: null,
      performedBy: 'Gate Pass Scenario Seeder',
      notes: `[GP-SCENARIO] ${scenario.trainNumber}; fill gate-pass dates during testing`,
    }),
  );
}

main().catch((error) => {
  console.error('Gate-pass train scenario seed failed:', error);
  process.exit(1);
});
