import { MigrationInterface, QueryRunner } from 'typeorm';

/**
 * Intercity (DOMESTIC) cargo is loaded at its origin yard and unloaded at its
 * destination yard, but only some yards have the equipment to do it. EDR's
 * load/unload facilities are Indode, Sebeta, Modjo, Adama, Dire Dawa and Negad —
 * and the set grows, so it must be data, not a constant.
 *
 * `yards.has_facility` marks a yard as a load/unload point; `yard_facilities`
 * holds what that facility can do. Only a facility with `has_warehouse` (Indode
 * today) stores cargo, and therefore accrues storage/demurrage — the rest just
 * move it on and off the train.
 *
 * `facility_handling_events` records each load/unload and carries its GRN.
 * warehouse_inventory can't do that job: its warehouse/yard/zone are NOT NULL, so
 * a facility with no warehouse could never have a row. `inventory_id` links to the
 * storage record when the facility does have a warehouse.
 */
export class YardFacilities2290000000000 implements MigrationInterface {
  name = 'YardFacilities2290000000000';

  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`
      ALTER TABLE freight.yards
        ADD COLUMN IF NOT EXISTS has_facility boolean NOT NULL DEFAULT false
    `);

    await queryRunner.query(`
      CREATE TABLE IF NOT EXISTS freight.yard_facilities (
        id              uuid PRIMARY KEY DEFAULT gen_random_uuid(),
        yard_id         uuid NOT NULL REFERENCES freight.yards(id) ON DELETE CASCADE,
        has_warehouse   boolean NOT NULL DEFAULT false,
        equipment_notes text NULL,
        is_active       boolean NOT NULL DEFAULT true,
        created_at      timestamptz NOT NULL DEFAULT now(),
        updated_at      timestamptz NOT NULL DEFAULT now(),
        deleted_at      timestamptz NULL
      )
    `);
    // One facility record per yard.
    await queryRunner.query(`
      CREATE UNIQUE INDEX IF NOT EXISTS "UQ_yard_facility_yard"
        ON freight.yard_facilities (yard_id) WHERE deleted_at IS NULL
    `);

    await queryRunner.query(`
      CREATE TABLE IF NOT EXISTS freight.facility_handling_events (
        id                uuid PRIMARY KEY DEFAULT gen_random_uuid(),
        booking_id        uuid NOT NULL REFERENCES freight.bookings(id),
        yard_id           uuid NOT NULL REFERENCES freight.yards(id),
        train_schedule_id uuid NULL REFERENCES freight.train_schedules(id),
        event_type        varchar(10) NOT NULL,
        grn_number        varchar(60) NULL,
        quantity          numeric(14, 3) NULL,
        weight_tons       numeric(14, 3) NULL,
        inventory_id      uuid NULL REFERENCES freight.warehouse_inventory(id),
        performed_by      varchar(120) NULL,
        occurred_at       timestamptz NOT NULL DEFAULT now(),
        created_at        timestamptz NOT NULL DEFAULT now(),
        updated_at        timestamptz NOT NULL DEFAULT now(),
        deleted_at        timestamptz NULL
      )
    `);
    await queryRunner.query(`
      CREATE INDEX IF NOT EXISTS "IDX_facility_handling_events_booking"
        ON freight.facility_handling_events (booking_id)
    `);
    await queryRunner.query(`
      CREATE INDEX IF NOT EXISTS "IDX_facility_handling_events_yard"
        ON freight.facility_handling_events (yard_id)
    `);
    await queryRunner.query(`
      CREATE INDEX IF NOT EXISTS "IDX_facility_handling_events_grn"
        ON freight.facility_handling_events (grn_number) WHERE grn_number IS NOT NULL
    `);
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`DROP TABLE IF EXISTS freight.facility_handling_events`);
    await queryRunner.query(`DROP TABLE IF EXISTS freight.yard_facilities`);
    await queryRunner.query(`
      ALTER TABLE freight.yards DROP COLUMN IF EXISTS has_facility
    `);
  }
}
