import { MigrationInterface, QueryRunner } from 'typeorm';

/**
 * Segment corridor bookings: a booking may ride only part of a train's route
 * (its own origin→destination leg), so dispatch/arrival become per-booking
 * facts and wagon capacity is consumed per leg instead of per whole route.
 *
 *  - bookings.loaded_at / arrived_at (+ by-user): operator-confirmed load at
 *    the booking's origin yard and unload at its destination yard. Clearance
 *    gates read arrived_at, not the train's actual_arrival_at.
 *  - train_set_wagons.board_yard_id / alight_yard_id: the leg a consist slot
 *    occupies; NULL/NULL = whole route (legacy). Non-overlapping legs coexist
 *    without consuming each other's capacity.
 *  - wagon_movements: auditable ledger of every physical wagon relocation
 *    (loaded leg / empty reposition / manual correction) with the acting user.
 */
export class SegmentCorridorBookings1990000000000 implements MigrationInterface {
  name = 'SegmentCorridorBookings1990000000000';

  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`
      ALTER TABLE freight.bookings
        ADD COLUMN IF NOT EXISTS loaded_at timestamptz,
        ADD COLUMN IF NOT EXISTS loaded_by_user_id uuid,
        ADD COLUMN IF NOT EXISTS arrived_at timestamptz,
        ADD COLUMN IF NOT EXISTS arrived_by_user_id uuid;
    `);

    await queryRunner.query(`
      ALTER TABLE freight.train_set_wagons
        ADD COLUMN IF NOT EXISTS board_yard_id uuid REFERENCES freight.yards(id) ON DELETE SET NULL,
        ADD COLUMN IF NOT EXISTS alight_yard_id uuid REFERENCES freight.yards(id) ON DELETE SET NULL;
    `);

    await queryRunner.query(`
      CREATE TABLE IF NOT EXISTS freight.wagon_movements (
        id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
        wagon_id uuid NOT NULL REFERENCES freight.wagons(id) ON DELETE CASCADE,
        from_yard_id uuid REFERENCES freight.yards(id),
        to_yard_id uuid NOT NULL REFERENCES freight.yards(id),
        train_schedule_id uuid REFERENCES freight.train_schedules(id) ON DELETE SET NULL,
        booking_id uuid REFERENCES freight.bookings(id) ON DELETE SET NULL,
        kind varchar(30) NOT NULL,
        moved_by_user_id uuid,
        occurred_at timestamptz NOT NULL DEFAULT now(),
        note text,
        created_at timestamptz NOT NULL DEFAULT now(),
        updated_at timestamptz NOT NULL DEFAULT now(),
        deleted_at timestamptz
      );
    `);
    await queryRunner.query(
      `CREATE INDEX IF NOT EXISTS "IDX_wagon_movements_wagon_occurred" ON freight.wagon_movements (wagon_id, occurred_at);`,
    );
    await queryRunner.query(
      `CREATE INDEX IF NOT EXISTS "IDX_wagon_movements_schedule" ON freight.wagon_movements (train_schedule_id);`,
    );
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`DROP TABLE IF EXISTS freight.wagon_movements;`);
    await queryRunner.query(`
      ALTER TABLE freight.train_set_wagons
        DROP COLUMN IF EXISTS board_yard_id,
        DROP COLUMN IF EXISTS alight_yard_id;
    `);
    await queryRunner.query(`
      ALTER TABLE freight.bookings
        DROP COLUMN IF EXISTS loaded_at,
        DROP COLUMN IF EXISTS loaded_by_user_id,
        DROP COLUMN IF EXISTS arrived_at,
        DROP COLUMN IF EXISTS arrived_by_user_id;
    `);
  }
}
