import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '../common/prisma.service';

const SEED_FLAG = 'SEED_SEGMENT_FARES';

/**
 * Seeds SegmentFareRule rows for every origin→destination pair on the
 * Addis Ababa–Djibouti route across all active seat classes.
 *
 * Skip-if-loaded: uses Prisma upsert on the unique constraint
 * (routeId, originStopSequence, destinationStopSequence, seatClassId, nationality).
 * Re-running is safe — existing rows are updated in-place.
 */
@Injectable()
export class SegmentFareSeeder {
  private readonly logger = new Logger(SegmentFareSeeder.name);

  constructor(private readonly prisma: PrismaService) {}

  async run() {
    if (process.env[SEED_FLAG]?.trim().toLowerCase() !== 'true') {
      this.logger.log(`Skipping segment fare seed — set ${SEED_FLAG}=true to enable`);
      return;
    }

    const route = await this.prisma.route.findFirst({
      where: { active: true },
      include: { stops: { orderBy: { sequence: 'asc' } } },
    });

    if (!route) {
      this.logger.warn('No active route found — skipping segment fare seed');
      return;
    }

    const seatClasses = await this.prisma.seatClass.findMany({
      where: { isActive: true },
    });

    if (!seatClasses.length) {
      this.logger.warn('No active seat classes found — skipping segment fare seed');
      return;
    }

    const stops = route.stops;
    const validFrom = new Date('2025-01-01T00:00:00.000Z');

    // Rate table: ETB minor units per km, keyed by (nationalityType, bedPosition)
    // null bedPosition = regular seat
    const rateTable: Record<string, Record<string | 'null', number>> = {
      LOCAL:         { null: 3000, UPPER: 4000, MIDDLE: 5500, LOWER: 6000 },
      INTERNATIONAL: { null: 6000, UPPER: 8000, MIDDLE: 11000, LOWER: 12000 },
    };

    let upserted = 0;

    for (const seatClass of seatClasses) {
      const natType = seatClass.nationalityType ?? 'LOCAL';
      const bedPos  = seatClass.bedPosition ?? 'null';
      const ratePerKm = rateTable[natType]?.[bedPos] ?? rateTable['LOCAL']['null'];

      for (let i = 0; i < stops.length - 1; i++) {
        for (let j = i + 1; j < stops.length; j++) {
          const origin = stops[i];
          const dest   = stops[j];

          // Approximate distance: sum of per-stop distanceKm if available,
          // otherwise fall back to sequence-gap × 50 km.
          let distanceKm = 0;
          for (let k = i; k < j; k++) {
            distanceKm += stops[k + 1].distanceKm ?? 50;
          }

          const baseFareMinor = Math.round(distanceKm * ratePerKm);

          await this.prisma.segmentFareRule.upsert({
            where: {
              routeId_originStopSequence_destinationStopSequence_seatClassId_nationality: {
                routeId:                 route.id,
                originStopSequence:      origin.sequence,
                destinationStopSequence: dest.sequence,
                seatClassId:             seatClass.id,
                nationality:             natType,
              },
            },
            update: { baseFareMinor, validFrom },
            create: {
              routeId:                 route.id,
              originStopSequence:      origin.sequence,
              destinationStopSequence: dest.sequence,
              seatClassId:             seatClass.id,
              nationality:             natType,
              baseFareMinor,
              currency:                'ETB',
              validFrom,
            },
          });

          upserted++;
        }
      }
    }

    this.logger.log(
      `Segment fare seed complete — ${upserted} rules upserted ` +
      `(${stops.length} stops × ${seatClasses.length} seat classes)`,
    );
  }
}
