import { MigrationInterface, QueryRunner } from 'typeorm';

/**
 * Configured rail distance between two yards (Configuration → Yard Distances).
 * Route creation resolves each segment's km from here (symmetric lookup:
 * one A↔B row serves both directions) instead of accepting free-text km,
 * and snapshots the value onto route_milestones.distance_km.
 *
 * Uniqueness is a partial index (deleted_at IS NULL) so a soft-deleted pair
 * can be re-created.
 */
export class CreateYardDistances2060000000000 implements MigrationInterface {
  name = 'CreateYardDistances2060000000000';

  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`
      CREATE TABLE IF NOT EXISTS freight.yard_distances (
        id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
        from_yard_id uuid NOT NULL REFERENCES freight.yards(id),
        to_yard_id uuid NOT NULL REFERENCES freight.yards(id),
        distance_km numeric(10,2) NOT NULL,
        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_yard_distances_from_yard
        ON freight.yard_distances (from_yard_id);
    `);
    await queryRunner.query(`
      CREATE INDEX IF NOT EXISTS idx_yard_distances_to_yard
        ON freight.yard_distances (to_yard_id);
    `);
    await queryRunner.query(`
      CREATE UNIQUE INDEX IF NOT EXISTS uq_yard_distances_pair
        ON freight.yard_distances (from_yard_id, to_yard_id)
        WHERE deleted_at IS NULL;
    `);
    // Backfill from segments already stored on existing routes so editing them
    // does not immediately fail the "pair not configured" check. One row per
    // unordered pair; where routes disagree the longest segment wins.
    await queryRunner.query(`
      INSERT INTO freight.yard_distances (from_yard_id, to_yard_id, distance_km)
      SELECT DISTINCT ON (LEAST(prev_yard_id, yard_id), GREATEST(prev_yard_id, yard_id))
        prev_yard_id, yard_id, distance_km
      FROM (
        SELECT
          yard_id,
          distance_km,
          LAG(yard_id) OVER (PARTITION BY route_id ORDER BY sequence_no) AS prev_yard_id
        FROM freight.route_milestones
        WHERE deleted_at IS NULL
      ) segments
      WHERE prev_yard_id IS NOT NULL
        AND distance_km IS NOT NULL
        AND distance_km > 0
      ORDER BY LEAST(prev_yard_id, yard_id), GREATEST(prev_yard_id, yard_id), distance_km DESC
      ON CONFLICT DO NOTHING;
    `);
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`DROP TABLE IF EXISTS freight.yard_distances;`);
  }
}
