import { MigrationInterface, QueryRunner } from 'typeorm';

/**
 * Repairs `freight.warehouse_inventory.grn_number`.
 *
 * AddGrnNumberToWarehouseInventory1828000000000 is recorded in `migrations` but
 * the column is absent on at least one environment - it was added, then dropped
 * out-of-band (a stray `synchronize: true`, same class of damage that
 * RepairSynchronizeDrift1870000000000 already had to undo). Because TypeORM has
 * the original recorded, it will never re-run it.
 *
 * Without the column, everything that reads or writes a GRN fails with
 * `column ... grn_number does not exist`:
 *   - bulkReceive()             -> INSERT names grn_number  (receive to warehouse)
 *   - importQueueByStatuses()   -> Unloaded + Dispatch queues
 *   - exportInventoryByStatus() -> Received / Ready-To-Load / Loaded tabs
 *   - grnDocument()             -> GRN PDF
 *
 * Idempotent: a no-op on environments where the column survived.
 */
export class RepairGrnNumberColumn2090000000000 implements MigrationInterface {
  name = 'RepairGrnNumberColumn2090000000000';

  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`
      ALTER TABLE freight.warehouse_inventory
      ADD COLUMN IF NOT EXISTS grn_number VARCHAR(100) NULL
    `);

    // Recover the GRN for rows received before the column existed: it was also
    // written into the receive note as "GRN Number: <value>".
    await queryRunner.query(`
      UPDATE freight.warehouse_inventory
         SET grn_number = substring(notes FROM 'GRN Number: ([^\\n\\r]+)')
       WHERE grn_number IS NULL
         AND notes IS NOT NULL
         AND notes ~ 'GRN Number: '
    `);

    await queryRunner.query(`
      CREATE INDEX IF NOT EXISTS idx_warehouse_inventory_grn_number
      ON freight.warehouse_inventory(grn_number)
      WHERE grn_number IS NOT NULL
    `);
  }

  /**
   * Deliberately a no-op. Dropping the column is what broke these environments
   * in the first place, and the original 1828 migration already owns its own
   * down(). Reverting this repair must not re-introduce the outage.
   */
  public async down(): Promise<void> {
    // intentionally empty
  }
}
