import { PrismaClient, SeatKind } from '@prisma/client';
import * as bcrypt from 'bcrypt';

const prisma = new PrismaClient();

async function main() {
  console.log('🌱 Starting complete seed...\n');

  // 1. STATIONS
  console.log('📍 Seeding stations...');
  const stationData = [
    { code: 'SBT', name: 'Sebeta', city: 'Sebeta', countryCode: 'ET', lat: 8.9167, lng: 38.6167 },
    { code: 'LBU', name: 'Labu', city: 'Labu', countryCode: 'ET', lat: 8.8500, lng: 38.7000 },
    { code: 'IND', name: 'Indode', city: 'Indode', countryCode: 'ET', lat: 8.7800, lng: 38.8200 },
    { code: 'BSH', name: 'Bishoftu', city: 'Bishoftu', countryCode: 'ET', lat: 8.7500, lng: 38.9833 },
    { code: 'MJO', name: 'Mojo', city: 'Mojo', countryCode: 'ET', lat: 8.6000, lng: 39.1200 },
    { code: 'ADM', name: 'Adama', city: 'Adama', countryCode: 'ET', lat: 8.5400, lng: 39.2675 },
    { code: 'DDW', name: 'Diredawa', city: 'Diredawa', countryCode: 'ET', lat: 9.5931, lng: 41.8661 },
    { code: 'NGD', name: 'Nagad', city: 'Nagad', countryCode: 'DJ', timezone: 'Africa/Djibouti', lat: 11.5720, lng: 43.1456 },
  ];
  
  const stations = [];
  for (const s of stationData) {
    stations.push(await prisma.station.upsert({ where: { code: s.code }, update: {}, create: s }));
  }
  console.log(`✅ ${stations.length} stations\n`);

  // 2. SEAT CLASSES
  console.log('💺 Seeding seat classes...');
  const scEconomy = await prisma.seatClass.upsert({
    where: { name: 'Economy Regular' },
    update: {},
    create: { name: 'Economy Regular', description: 'Standard economy', basePrice: 25000, isActive: true },
  });
  const scBed = await prisma.seatClass.upsert({
    where: { name: 'Economy Bed' },
    update: {},
    create: { name: 'Economy Bed', description: 'Economy bed', basePrice: 35000, isActive: true },
  });
  console.log(`✅ 2 seat classes\n`);

  // 3. ROUTES
  console.log('🛤️  Seeding routes...');
  const route1 = await prisma.route.upsert({
    where: { code: 'SBT-NGD' },
    update: {},
    create: { code: 'SBT-NGD', name: 'Sebeta-Nagad Express', effectiveFrom: new Date('2026-01-01'), active: true },
  });
  
  await prisma.routeStop.createMany({
    data: [
      { routeId: route1.id, stationId: stations[0].id, sequence: 1, distanceKm: 0 },
      { routeId: route1.id, stationId: stations[1].id, sequence: 2, distanceKm: 15 },
      { routeId: route1.id, stationId: stations[2].id, sequence: 3, distanceKm: 28 },
      { routeId: route1.id, stationId: stations[3].id, sequence: 4, distanceKm: 45 },
      { routeId: route1.id, stationId: stations[4].id, sequence: 5, distanceKm: 73 },
      { routeId: route1.id, stationId: stations[5].id, sequence: 6, distanceKm: 99 },
      { routeId: route1.id, stationId: stations[6].id, sequence: 7, distanceKm: 378 },
      { routeId: route1.id, stationId: stations[7].id, sequence: 8, distanceKm: 756 },
    ],
    skipDuplicates: true,
  });

  await prisma.routeFareRule.createMany({
    data: [
      { routeId: route1.id, seatClassId: scEconomy.id, passengerCategory: 'ADULT', baseFareMinor: 65000, validFrom: new Date('2026-01-01') },
      { routeId: route1.id, seatClassId: scEconomy.id, passengerCategory: 'CHILD', baseFareMinor: 65000, validFrom: new Date('2026-01-01') },
      { routeId: route1.id, seatClassId: scBed.id, passengerCategory: 'ADULT', baseFareMinor: 91000, validFrom: new Date('2026-01-01') },
      { routeId: route1.id, seatClassId: scBed.id, passengerCategory: 'CHILD', baseFareMinor: 91000, validFrom: new Date('2026-01-01') },
    ],
    skipDuplicates: true,
  });
  console.log(`✅ 1 route with stops and fares\n`);

  // 4. TRAINS
  console.log('🚂 Seeding trains...');
  const train = await prisma.train.upsert({
    where: { number: '301' },
    update: {},
    create: { number: '301', name: 'Express 301', description: 'Main Express' },
  });
  console.log(`✅ 1 train\n`);

  // 5. COACHES & SEATS
  console.log('🚃 Seeding coaches...');
  const coach1 = await prisma.coach.upsert({
    where: { coachNumber: 'C-A1' },
    update: {},
    create: { coachNumber: 'C-A1', label: 'A', seatClassId: scEconomy.id, mode: 'seat', totalUnits: 20 },
  });

  const existingSeats = await prisma.seat.count({ where: { coachId: coach1.id } });
  if (existingSeats === 0) {
    const seats = [];
    for (let row = 1; row <= 5; row++) {
      for (const col of ['A', 'B', 'C', 'D']) {
        seats.push({
          coachId: coach1.id,
          row,
          col,
          label: `${row}${col}`,
          seatNumber: `A${row}${col}`,
          kind: 'STANDARD' as SeatKind,
        });
      }
    }
    await prisma.seat.createMany({ data: seats });
  }
  console.log(`✅ 1 coach with 20 seats\n`);

  // 6. SCHEDULE
  console.log('📅 Seeding schedule...');
  const existingSchedules = await prisma.trainSchedule.findMany({ where: { trainId: train.id }, select: { id: true } });
  if (existingSchedules.length > 0) {
    const scheduleIds = existingSchedules.map(s => s.id);
    // Delete in correct order to avoid foreign key constraints
    await prisma.bookingSeat.deleteMany({ where: { booking: { scheduleId: { in: scheduleIds } } } });
    await prisma.booking.deleteMany({ where: { scheduleId: { in: scheduleIds } } });
    await prisma.fareRule.deleteMany({ where: { tripId: { in: scheduleIds } } });
    await prisma.tripStopTime.deleteMany({ where: { scheduleId: { in: scheduleIds } } });
    await prisma.coachAssignment.deleteMany({ where: { scheduleId: { in: scheduleIds } } });
    await prisma.trainSchedule.deleteMany({ where: { trainId: train.id } });
  }
  
  const schedule = await prisma.trainSchedule.create({
    data: {
      trainId: train.id,
      routeId: route1.id,
      originStationId: stations[0].id,
      destinationStationId: stations[7].id,
      departureAt: new Date('2026-06-15T06:00:00Z'),
      arrivalAt: new Date('2026-06-15T22:00:00Z'),
      durationMinutes: 960,
      stopsCount: 8,
    },
  });

  await prisma.coachAssignment.create({
    data: { scheduleId: schedule.id, coachId: coach1.id, positionNumber: 1 },
  });

  await prisma.tripStopTime.createMany({
    data: [
      { scheduleId: schedule.id, stationId: stations[0].id, sequence: 1, plannedDepartureAt: new Date('2026-06-15T06:00:00Z'), status: 'UPCOMING' },
      { scheduleId: schedule.id, stationId: stations[1].id, sequence: 2, plannedArrivalAt: new Date('2026-06-15T07:00:00Z'), plannedDepartureAt: new Date('2026-06-15T07:05:00Z'), status: 'UPCOMING' },
      { scheduleId: schedule.id, stationId: stations[2].id, sequence: 3, plannedArrivalAt: new Date('2026-06-15T08:00:00Z'), plannedDepartureAt: new Date('2026-06-15T08:05:00Z'), status: 'UPCOMING' },
      { scheduleId: schedule.id, stationId: stations[3].id, sequence: 4, plannedArrivalAt: new Date('2026-06-15T09:00:00Z'), plannedDepartureAt: new Date('2026-06-15T09:10:00Z'), status: 'UPCOMING' },
      { scheduleId: schedule.id, stationId: stations[4].id, sequence: 5, plannedArrivalAt: new Date('2026-06-15T10:00:00Z'), plannedDepartureAt: new Date('2026-06-15T10:10:00Z'), status: 'UPCOMING' },
      { scheduleId: schedule.id, stationId: stations[5].id, sequence: 6, plannedArrivalAt: new Date('2026-06-15T11:00:00Z'), plannedDepartureAt: new Date('2026-06-15T11:15:00Z'), status: 'UPCOMING' },
      { scheduleId: schedule.id, stationId: stations[6].id, sequence: 7, plannedArrivalAt: new Date('2026-06-15T15:00:00Z'), plannedDepartureAt: new Date('2026-06-15T15:20:00Z'), status: 'UPCOMING' },
      { scheduleId: schedule.id, stationId: stations[7].id, sequence: 8, plannedArrivalAt: new Date('2026-06-15T22:00:00Z'), status: 'UPCOMING' },
    ],
  });
  console.log(`✅ 1 schedule with stops\n`);

  // 7. USERS
  console.log('👥 Seeding users...');
  const adminHash = await bcrypt.hash('admin123', 10);
  const userHash = await bcrypt.hash('password123', 10);

  await prisma.user.upsert({
    where: { email: 'admin@edr-platform.com' },
    update: {},
    create: { fullName: 'Admin', email: 'admin@edr-platform.com', phone: '+251900000000', passwordHash: adminHash, role: 'ADMIN' },
  });

  const user = await prisma.user.upsert({
    where: { email: 'abebe@email.com' },
    update: {},
    create: { fullName: 'Abebe Kebede', email: 'abebe@email.com', phone: '+251912345678', passwordHash: userHash, nationality: 'Ethiopian' },
  });

  let passenger = await prisma.passenger.findUnique({ where: { userId: user.id } });
  if (!passenger) {
    passenger = await prisma.passenger.create({ data: { userId: user.id } });
    await prisma.loyaltyAccount.create({ data: { passengerId: passenger.id, pointsBalance: 1000, tier: 'BRONZE' } });
    await prisma.walletAccount.create({ data: { passengerId: passenger.id, balanceMinor: 100000 } });
  }
  console.log(`✅ 2 users\n`);

  // 8. SUPPORTING DATA
  console.log('📦 Seeding supporting data...');
  
  await prisma.paymentMethod.upsert({
    where: { type: 'TELEBIRR' },
    update: {},
    create: { type: 'TELEBIRR', displayName: 'Telebirr', region: 'ETHIOPIA', currency: 'ETB', enabled: true, sortOrder: 1 },
  });

  await prisma.currencyExchangeRate.deleteMany({});
  await prisma.currencyExchangeRate.createMany({
    data: [
      { fromCurrency: 'ETB', toCurrency: 'ETB', rate: 1.0, effectiveDate: new Date() },
      { fromCurrency: 'ETB', toCurrency: 'USD', rate: 0.018, effectiveDate: new Date() },
      { fromCurrency: 'ETB', toCurrency: 'DJF', rate: 3.2, effectiveDate: new Date() },
    ],
  });
  console.log(`✅ Payment methods and currencies\n`);

  console.log('✅ SEED COMPLETE!\n');
  console.log('📋 Summary:');
  console.log('  - 8 Stations');
  console.log('  - 2 Seat Classes');
  console.log('  - 1 Route with 8 stops');
  console.log('  - 1 Train with 1 schedule');
  console.log('  - 1 Coach with 20 seats');
  console.log('  - 2 Users (Admin + Passenger)');
  console.log('\n🔑 Credentials:');
  console.log('  Admin: admin@edr-platform.com / admin123');
  console.log('  User: abebe@email.com / password123');
}

main()
  .catch((e) => {
    console.error('❌ Error:', e);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
