import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddBookingsConfigForeignKeys1748700000000 implements MigrationInterface {
  name = 'AddBookingsConfigForeignKeys1748700000000';

  public async up(queryRunner: QueryRunner): Promise<void> {
    // Ensure parent config rows exist for backfill
    await queryRunner.query(`
      INSERT INTO freight.service_types (id, code, service_name, can_be_booked_alone, includes_first_mile, includes_last_mile, includes_customs, priority_bonus_points, is_active, display_order, created_at, updated_at)
      SELECT uuid_generate_v4(), 'RAIL', 'Rail Transport Only', true, false, false, false, 0, true, 1, now(), now()
      WHERE NOT EXISTS (SELECT 1 FROM freight.service_types LIMIT 1);
    `);
    await queryRunner.query(`
      INSERT INTO freight.cargo_types (id, code, cargo_type_name, requires_director_approval, show_free_text_box, is_active, display_order, created_at, updated_at)
      SELECT uuid_generate_v4(), 'GENERAL', 'General Cargo', false, false, true, 1, now(), now()
      WHERE NOT EXISTS (SELECT 1 FROM freight.cargo_types LIMIT 1);
    `);

    // Clear orphan shipping_line references (nullable FK)
    await queryRunner.query(`
      UPDATE freight.bookings b
      SET shipping_line_id = NULL
      WHERE b.shipping_line_id IS NOT NULL
        AND NOT EXISTS (
          SELECT 1 FROM freight.shipping_lines sl WHERE sl.id = b.shipping_line_id
        );
    `);

    // Backfill required FK columns
    await queryRunner.query(`
      UPDATE freight.bookings
      SET service_type_id = (SELECT id FROM freight.service_types ORDER BY display_order LIMIT 1)
      WHERE service_type_id IS NULL
         OR NOT EXISTS (SELECT 1 FROM freight.service_types st WHERE st.id = service_type_id);
    `);
    await queryRunner.query(`
      UPDATE freight.bookings
      SET cargo_type_id = (SELECT id FROM freight.cargo_types ORDER BY display_order LIMIT 1)
      WHERE cargo_type_id IS NULL
         OR NOT EXISTS (SELECT 1 FROM freight.cargo_types ct WHERE ct.id = cargo_type_id);
    `);

    await queryRunner.query(`
      DO $$ BEGIN
        ALTER TABLE freight.bookings
          ADD CONSTRAINT "FK_bookings_service_type_id"
          FOREIGN KEY (service_type_id)
          REFERENCES freight.service_types(id)
          ON DELETE RESTRICT;
      EXCEPTION
        WHEN duplicate_object THEN NULL;
      END $$;
    `);

    await queryRunner.query(`
      DO $$ BEGIN
        ALTER TABLE freight.bookings
          ADD CONSTRAINT "FK_bookings_cargo_type_id"
          FOREIGN KEY (cargo_type_id)
          REFERENCES freight.cargo_types(id)
          ON DELETE RESTRICT;
      EXCEPTION
        WHEN duplicate_object THEN NULL;
      END $$;
    `);

    await queryRunner.query(`
      DO $$ BEGIN
        ALTER TABLE freight.bookings
          ADD CONSTRAINT "FK_bookings_shipping_line_id"
          FOREIGN KEY (shipping_line_id)
          REFERENCES freight.shipping_lines(id)
          ON DELETE SET NULL;
      EXCEPTION
        WHEN duplicate_object THEN NULL;
      END $$;
    `);
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`
      ALTER TABLE freight.bookings
        DROP CONSTRAINT IF EXISTS "FK_bookings_shipping_line_id";
    `);
    await queryRunner.query(`
      ALTER TABLE freight.bookings
        DROP CONSTRAINT IF EXISTS "FK_bookings_cargo_type_id";
    `);
    await queryRunner.query(`
      ALTER TABLE freight.bookings
        DROP CONSTRAINT IF EXISTS "FK_bookings_service_type_id";
    `);
  }
}
