import { Injectable, Logger } from '@nestjs/common';
import { DataSource } from 'typeorm';

import { Booking } from '../modules/bookings/entities/booking.entity';
import { ServiceType } from '../modules/rule-engine/entities/service-type.entity';
import { Yard } from '../modules/rule-engine/entities/yard.entity';
import { Warehouse } from '../modules/warehouses/entities/warehouse.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';

const SEED_REFS = ['SEED-B5-EXP-001', 'SEED-B5-EXP-002', 'SEED-B5-EXP-003'];

const SEEDS = [
  { ref: 'SEED-B5-EXP-001', weight: 5000, notes: 'Electronics export cargo' },
  { ref: 'SEED-B5-EXP-002', weight: 8500, notes: 'Textile export cargo' },
  { ref: 'SEED-B5-EXP-003', weight: 3200, notes: 'Coffee export cargo' },
];

/**
 * Seeds 3 EXPORT+PAID bookings with READY_FOR_LOADING + inspection PASSED inventory
 * so the Batch 5 "Ready To Load" tab has visible rows to test against.
 *
 * Origin: any Ethiopian yard (route-based direction = EXPORT when dest = Djibouti)
 * Destination: any Djiboutian yard
 * Uses the INDODE_OPEN warehouse created by IndodeFacilitySeeder.
 */
@Injectable()
export class Batch5TestDataSeeder {
  private readonly logger = new Logger(Batch5TestDataSeeder.name);

  constructor(private readonly dataSource: DataSource) {}

  async run(): Promise<void> {
    const bookingRepo = this.dataSource.getRepository(Booking);

    const existing = await bookingRepo.findOne({ where: { reference: SEED_REFS[0] } });
    if (existing) {
      this.logger.log('Batch 5 test data already seeded, skipping');
      return;
    }

    try {
      const yardRepo = this.dataSource.getRepository(Yard);
      const serviceTypeRepo = this.dataSource.getRepository(ServiceType);
      const warehouseRepo = this.dataSource.getRepository(Warehouse);
      const warehouseYardRepo = this.dataSource.getRepository(WarehouseYard);
      const warehouseZoneRepo = this.dataSource.getRepository(WarehouseZone);
      const inventoryRepo = this.dataSource.getRepository(WarehouseInventory);

      // Find Ethiopian origin yard and Djiboutian destination yard.
      const originYard =
        (await yardRepo.findOne({ where: { code: 'ADDIS_ABABA' } })) ??
        (await yardRepo.findOne({ where: { country: 'Ethiopia' } }));
      const destYard =
        (await yardRepo.findOne({ where: { code: 'DJIBOUTI' } })) ??
        (await yardRepo.findOne({ where: { country: 'Djibouti' } }));

      if (!originYard || !destYard) {
        this.logger.warn(
          `Required yards not found (origin=${originYard?.code ?? 'none'}, dest=${destYard?.code ?? 'none'}); skipping Batch 5 seed`,
        );
        return;
      }

      // Find any active service type (bookings require one).
      const serviceType =
        (await serviceTypeRepo.findOne({ where: { code: 'RAIL_CONTAINER' } })) ??
        (await serviceTypeRepo.findOne({ where: { isActive: true } }));
      if (!serviceType) {
        this.logger.warn('No service type found; skipping Batch 5 seed');
        return;
      }

      // Find INDODE warehouse.
      const warehouse = await warehouseRepo.findOne({ where: { code: 'INDODE_OPEN' } });
      if (!warehouse) {
        this.logger.warn('INDODE_OPEN warehouse not found; skipping Batch 5 seed');
        return;
      }

      const warehouseYard = await warehouseYardRepo.findOne({ where: { warehouseId: warehouse.id } });
      if (!warehouseYard) {
        this.logger.warn('No warehouse yard found for INDODE_OPEN; skipping Batch 5 seed');
        return;
      }

      const warehouseZone = await warehouseZoneRepo.findOne({ where: { yardId: warehouseYard.id } });
      if (!warehouseZone) {
        this.logger.warn('No warehouse zone found; skipping Batch 5 seed');
        return;
      }

      const now = new Date();

      for (const seed of SEEDS) {
        const booking = await bookingRepo.save(
          bookingRepo.create({
            reference: seed.ref,
            originYardId: originYard.id,
            destinationYardId: destYard.id,
            serviceTypeId: serviceType.id,
            status: 'PAID',
            paymentStatus: 'PAID',
            tradeDirection: 'EXPORT',
            freightType: 'BULK',
            cargoTotalWeightVgm: seed.weight,
            cargoFreeText: seed.notes,
          }),
        );

        await inventoryRepo.save(
          inventoryRepo.create({
            bookingId: booking.id,
            warehouseId: warehouse.id,
            yardId: warehouseYard.id,
            zoneId: warehouseZone.id,
            status: 'READY_FOR_LOADING',
            inspectionStatus: 'PASSED',
            inspectedAt: new Date(now.getTime() - 3600 * 1000),
            quantity: 1,
            weight: seed.weight,
            arrivedAt: new Date(now.getTime() - 7200 * 1000),
            readyForLoadingAt: new Date(now.getTime() - 1800 * 1000),
            notes: `[SEED-B5] ${seed.notes}`,
          }),
        );

        this.logger.log(`Seeded ${seed.ref} → READY_FOR_LOADING + PASSED`);
      }

      this.logger.log('✅ Batch 5 Ready-To-Load test data seeded successfully');
    } catch (error) {
      this.logger.error(
        `Batch5TestDataSeeder failed: ${error instanceof Error ? error.message : String(error)}`,
      );
    }
  }
}
