import { AppDataSource } from '../data-source';
import { SeedEdrWagonFleetErNumbering2260000000000 } from '../migrations/2260000000000-SeedEdrWagonFleetErNumbering';
import { AddWagonTrainNumbers2270000000000 } from '../migrations/2270000000000-AddWagonTrainNumbers';
import { SeedWagonRunNumbers2280000000000 } from '../migrations/2280000000000-SeedWagonRunNumbers';
import { WagonNumberPartialUnique2280000000000 } from '../migrations/2280000000000-WagonNumberPartialUnique';
import { SeedWagonYardDoraleh2290000000000 } from '../migrations/2290000000000-SeedWagonYardDoraleh';

async function seedEdRWagons() {
  await AppDataSource.initialize();

  const queryRunner = AppDataSource.createQueryRunner();

  try {
    await queryRunner.connect();
    await queryRunner.startTransaction();

    // Fleet first (recreates every wagon with NULL yard + NULL runs), then the
    // columns are ensured to exist, then the run roster and the yard are applied
    // on top. Same order the migrations run in, so the script and a fresh
    // migrate agree.
    await new SeedEdrWagonFleetErNumbering2260000000000().up(queryRunner);
    await new AddWagonTrainNumbers2270000000000().up(queryRunner);
    // Not a wagon seed, but it owns wagon_number uniqueness — included so this
    // script leaves the same schema a real `migration:run` would, rather than a
    // database missing the partial unique index.
    await new WagonNumberPartialUnique2280000000000().up(queryRunner);
    await new SeedWagonRunNumbers2280000000000().up(queryRunner);
    await new SeedWagonYardDoraleh2290000000000().up(queryRunner);

    const summary = await queryRunner.query(`
      SELECT
        wt.code,
        wt.name,
        COUNT(*)::int AS wagons,
        MIN(w.wagon_number) AS first_wagon,
        MAX(w.wagon_number) AS last_wagon,
        COUNT(*) FILTER (WHERE w.status = 'AVAILABLE')::int AS available,
        COUNT(*) FILTER (WHERE w.current_yard_id IS NULL)::int AS no_yard,
        COUNT(*) FILTER (WHERE w.export_train_number IS NOT NULL)::int AS on_a_run
      FROM freight.wagons w
      JOIN freight.wagon_types wt ON wt.id = w.wagon_type_id
      WHERE w.wagon_number BETWEEN 'ER0001' AND 'ER1100'
      GROUP BY wt.code, wt.name
      ORDER BY MIN(w.wagon_number);
    `);

    const [totals] = await queryRunner.query(`
      SELECT
        COUNT(*)::int AS total,
        COUNT(*) FILTER (WHERE export_train_number IS NOT NULL)::int AS on_a_run
      FROM freight.wagons;
    `);

    const yards = await queryRunner.query(`
      SELECT
        COALESCE(y.label, '(no yard)') AS yard,
        COUNT(*)::int AS wagons
      FROM freight.wagons w
      LEFT JOIN freight.yards y ON y.id = w.current_yard_id
      GROUP BY y.label
      ORDER BY 2 DESC;
    `);

    const runs = await queryRunner.query(`
      SELECT
        export_train_number AS export_run,
        import_train_number AS import_run,
        COUNT(*)::int AS wagons
      FROM freight.wagons
      WHERE export_train_number IS NOT NULL
      GROUP BY export_train_number, import_train_number
      ORDER BY export_train_number;
    `);

    await queryRunner.commitTransaction();

    console.log('\nFleet by wagon type:');
    console.table(summary);
    console.log('Run roster (export/import pairs):');
    console.table(runs);
    console.log('Fleet by yard:');
    console.table(yards);
    console.log(
      `Seeded EDR wagon fleet — ${totals.total} wagons total (expected 1100), ` +
        `${totals.on_a_run} on a run (expected 533).`,
    );
  } catch (error) {
    await queryRunner.rollbackTransaction();
    throw error;
  } finally {
    await queryRunner.release();
    await AppDataSource.destroy();
  }
}

seedEdRWagons().catch((error) => {
  console.error('Failed to seed EDR wagon fleet:', error);
  process.exit(1);
});
