import { MigrationInterface, QueryRunner } from 'typeorm';

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

  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`CREATE SCHEMA IF NOT EXISTS freight`);

    await queryRunner.query(`
      CREATE TABLE IF NOT EXISTS freight.wagons (
        id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
        wagon_number VARCHAR NOT NULL UNIQUE,
        wagon_type_id UUID NOT NULL,
        train_id UUID,
        sequence_number INT,
        tare_weight NUMERIC(10, 2) NOT NULL,
        max_payload_weight NUMERIC(10, 2) NOT NULL,
        status VARCHAR NOT NULL DEFAULT 'AVAILABLE',
        notes TEXT,
        created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
        updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
        deleted_at TIMESTAMPTZ
      );
    `);

    await queryRunner.query(`
      CREATE TABLE IF NOT EXISTS freight.containers (
        id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
        container_number VARCHAR NOT NULL UNIQUE,
        container_type_id UUID NOT NULL,
        wagon_id UUID,
        position INT,
        tare_weight NUMERIC(10, 2) NOT NULL,
        max_gross_weight NUMERIC(10, 2) NOT NULL,
        seal_number VARCHAR,
        status VARCHAR NOT NULL DEFAULT 'AVAILABLE',
        created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
        updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
        deleted_at TIMESTAMPTZ
      );
    `);

    await queryRunner.query(`
      CREATE TABLE IF NOT EXISTS freight.cargoes (
        id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
        cargo_reference VARCHAR NOT NULL UNIQUE,
        shipment_id UUID NOT NULL,
        container_id UUID NOT NULL,
        cargo_type_id UUID,
        description TEXT,
        quantity NUMERIC(12, 3) NOT NULL,
        weight NUMERIC(10, 2) NOT NULL,
        volume NUMERIC(10, 2),
        status VARCHAR NOT NULL DEFAULT 'PENDING',
        loaded_at TIMESTAMP,
        unloaded_at TIMESTAMP,
        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_wagons_train_id" ON freight.wagons (train_id)`);
    await queryRunner.query(`CREATE INDEX IF NOT EXISTS "IDX_containers_wagon_id" ON freight.containers (wagon_id)`);
    await queryRunner.query(`CREATE INDEX IF NOT EXISTS "IDX_cargoes_container_id" ON freight.cargoes (container_id)`);

    await queryRunner.query(`
      DO $$ BEGIN
        ALTER TABLE freight.wagons
          ADD CONSTRAINT "FK_wagons_train_id"
          FOREIGN KEY (train_id) REFERENCES freight.trains(id) ON DELETE SET NULL;
      EXCEPTION WHEN duplicate_object THEN NULL;
      END $$;
    `);

    await queryRunner.query(`
      DO $$ BEGIN
        ALTER TABLE freight.wagons
          ADD CONSTRAINT "FK_wagons_wagon_type_id"
          FOREIGN KEY (wagon_type_id) REFERENCES freight.wagon_types(id);
      EXCEPTION WHEN duplicate_object THEN NULL;
      END $$;
    `);

    await queryRunner.query(`
      DO $$ BEGIN
        ALTER TABLE freight.containers
          ADD CONSTRAINT "FK_containers_wagon_id"
          FOREIGN KEY (wagon_id) REFERENCES freight.wagons(id) ON DELETE SET NULL;
      EXCEPTION WHEN duplicate_object THEN NULL;
      END $$;
    `);

    await queryRunner.query(`
      DO $$ BEGIN
        ALTER TABLE freight.containers
          ADD CONSTRAINT "FK_containers_container_type_id"
          FOREIGN KEY (container_type_id) REFERENCES freight.container_types(id);
      EXCEPTION WHEN duplicate_object THEN NULL;
      END $$;
    `);

    await queryRunner.query(`
      DO $$ BEGIN
        ALTER TABLE freight.cargoes
          ADD CONSTRAINT "FK_cargoes_container_id"
          FOREIGN KEY (container_id) REFERENCES freight.containers(id) ON DELETE RESTRICT;
      EXCEPTION WHEN duplicate_object THEN NULL;
      END $$;
    `);

    await queryRunner.query(`
      DO $$ BEGIN
        ALTER TABLE freight.cargoes
          ADD CONSTRAINT "FK_cargoes_cargo_type_id"
          FOREIGN KEY (cargo_type_id) REFERENCES freight.cargo_types(id);
      EXCEPTION WHEN duplicate_object THEN NULL;
      END $$;
    `);
  }

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