import { MigrationInterface, QueryRunner } from 'typeorm';

/**
 * Full wagon re-seed — runs in this order:
 *
 *   1. DELETE all existing wagons (hard delete, not soft).
 *   2. UPSERT all 10 standard wagon types so they are guaranteed to exist.
 *   3. INSERT 50 wagons per wagon type (500 total), distributed evenly across
 *      the 5 main operational yards (10 wagons per yard per type):
 *
 *        KALITY     — Kality Rail Terminal
 *        MOJO       — Mojo Dry Port
 *        DIRE_DAWA  — Dire Dawa Yard
 *        DJIB_PORT  — Djibouti Port Terminal
 *        NAGAD      — Nagad Terminal, Djibouti
 *
 * Wagon numbers follow the pattern <TYPE_CODE>-NNNN  (e.g. NW5-0001 … NW5-0050).
 * Yard IDs are fetched live from freight.yards so the migration is safe across
 * all environments regardless of UUID values.
 */
export class SeedWagonsWithYardAssignment1784000000001
  implements MigrationInterface
{
  name = 'SeedWagonsWithYardAssignment1784000000001';

  public async up(queryRunner: QueryRunner): Promise<void> {
    // ── STEP 1: Remove all wagons ──────────────────────────────────────────
    await queryRunner.query(`DELETE FROM freight.wagons;`);

    // ── STEP 2: Ensure all 10 wagon types exist ────────────────────────────
    await queryRunner.query(`
      INSERT INTO freight.wagon_types (
        code,
        name,
        capacity_tons,
        length_meters,
        max_wagons_per_train,
        supported_load_types,
        is_active,
        tare_weight_tons
      )
      VALUES
        ('NW7', 'Double deck sedan wagon',   22, 26.066, NULL, ARRAY['vehicles', 'sedan'],            true, 18.0),
        ('NW5', 'Flat wagon (container)',     70, 14.000,   53, ARRAY['container', 'steel', 'machinery'], true, 22.0),
        ('PW2', 'Box wagon',                 70, 17.066,   18, ARRAY['general cargo', 'break bulk'],  true, 20.0),
        ('GW2', 'Tank wagon',                70, 12.228,   37, ARRAY['liquid', 'fuel'],               true, 25.0),
        ('CW4', 'Gondola covered wagon',     70, 13.976,   37, ARRAY['covered bulk cargo'],           true, 22.0),
        ('CW3', 'Gondola open wagon',        70, 13.976, NULL, ARRAY['open bulk cargo'],              true, 20.0),
        ('KW2', 'Hopper covered wagon',      69, 16.466, NULL, ARRAY['bulk grains'],                  true, 22.0),
        ('KW3', 'Hopper open wagon',         70, 14.400, NULL, ARRAY['coal', 'bulk cargo'],           true, 20.0),
        ('NW6', 'Flat wagon (long cargo)',   70, 18.560, NULL, ARRAY['long cargo'],                   true, 22.0),
        ('BW1', 'Refrigerated wagon',        38, 21.996, NULL, ARRAY['refrigerated cargo'],           true, 24.0)
      ON CONFLICT (code) DO UPDATE SET
        name                 = EXCLUDED.name,
        capacity_tons        = EXCLUDED.capacity_tons,
        length_meters        = EXCLUDED.length_meters,
        max_wagons_per_train = EXCLUDED.max_wagons_per_train,
        supported_load_types = EXCLUDED.supported_load_types,
        is_active            = true,
        tare_weight_tons     = EXCLUDED.tare_weight_tons,
        deleted_at           = NULL,
        updated_at           = now();
    `);

    // ── STEP 3: Seed 50 wagons per type across 5 yards ────────────────────
    await queryRunner.query(`
      DO $$
      DECLARE
        wt             RECORD;
        yard_kality    UUID;
        yard_mojo      UUID;
        yard_dire_dawa UUID;
        yard_djib_port UUID;
        yard_nagad     UUID;
        yards          UUID[];
        i              INT;
        yard_id        UUID;
        wagon_num      TEXT;
        v_tare         NUMERIC;
        v_payload      NUMERIC;
      BEGIN
        -- Fetch yard IDs by code (safe across envs — UUIDs differ per DB)
        SELECT id INTO yard_kality    FROM freight.yards WHERE code = 'KALITY'    LIMIT 1;
        SELECT id INTO yard_mojo      FROM freight.yards WHERE code = 'MOJO'      LIMIT 1;
        SELECT id INTO yard_dire_dawa FROM freight.yards WHERE code = 'DIRE_DAWA' LIMIT 1;
        SELECT id INTO yard_djib_port FROM freight.yards WHERE code = 'DJIB_PORT' LIMIT 1;
        SELECT id INTO yard_nagad     FROM freight.yards WHERE code = 'NAGAD'     LIMIT 1;

        IF yard_kality IS NULL OR yard_mojo IS NULL OR yard_dire_dawa IS NULL
           OR yard_djib_port IS NULL OR yard_nagad IS NULL
        THEN
          RAISE EXCEPTION 'One or more operational yards not found. Run the yards seed first.';
        END IF;

        yards := ARRAY[
          yard_kality,
          yard_mojo,
          yard_dire_dawa,
          yard_djib_port,
          yard_nagad
        ];

        FOR wt IN
          SELECT id, code, capacity_tons, tare_weight_tons
          FROM   freight.wagon_types
          WHERE  is_active = true
          ORDER  BY code
        LOOP
          v_tare    := COALESCE(wt.tare_weight_tons, 20.0);
          v_payload := COALESCE(wt.capacity_tons, 60.0);

          FOR i IN 1 .. 50 LOOP
            wagon_num := wt.code || '-' || LPAD(i::TEXT, 4, '0');
            yard_id   := yards[ ((i - 1) % 5) + 1 ];  -- round-robin: 1→K, 2→M, 3→D, 4→J, 5→N, 6→K …

            INSERT INTO freight.wagons (
              id,
              wagon_number,
              wagon_type_id,
              tare_weight,
              max_payload_weight,
              status,
              current_yard_id,
              train_id,
              sequence_number,
              notes,
              train_set_wagon_id,
              current_train_schedule_id,
              created_at,
              updated_at
            )
            VALUES (
              uuid_generate_v4(),
              wagon_num,
              wt.id,
              v_tare,
              v_payload,
              'Available',
              yard_id,
              NULL, NULL, NULL, NULL, NULL,
              now(), now()
            )
            ON CONFLICT (wagon_number) DO NOTHING;
          END LOOP;

          RAISE NOTICE 'Seeded 50 wagons for type %.', wt.code;
        END LOOP;
      END $$;
    `);
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    // Remove all seeded wagons (full wipe — mirrors what up() did)
    await queryRunner.query(`DELETE FROM freight.wagons;`);
  }
}
