import { MigrationInterface, QueryRunner } from 'typeorm';

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

  public async up(queryRunner: QueryRunner): Promise<void> {
    // ── Capacity columns (weight + volume) on warehouse / yard / zone ──────
    for (const table of ['warehouses', 'warehouse_yards', 'warehouse_zones']) {
      await queryRunner.query(`
        ALTER TABLE freight.${table}
        ADD COLUMN IF NOT EXISTS max_weight NUMERIC(14,3) NULL,
        ADD COLUMN IF NOT EXISTS max_volume NUMERIC(14,3) NULL,
        ADD COLUMN IF NOT EXISTS current_volume NUMERIC(14,3) NOT NULL DEFAULT 0;
      `);
      // Backfill max_weight from the Batch 1 capacity_weight column.
      await queryRunner.query(`
        UPDATE freight.${table} SET max_weight = capacity_weight WHERE max_weight IS NULL;
      `);
    }

    // ── Inventory lifecycle: migrate Batch 1 statuses to Batch 2 set ───────
    await queryRunner.query(`
      ALTER TABLE freight.warehouse_inventory
      ALTER COLUMN status SET DEFAULT 'RECEIVED';
    `);
    await queryRunner.query(`
      UPDATE freight.warehouse_inventory SET status = 'RECEIVED' WHERE status = 'ARRIVED_AT_WAREHOUSE';
    `);
    await queryRunner.query(`
      UPDATE freight.warehouse_inventory SET status = 'STORED' WHERE status = 'UNDER_INSPECTION';
    `);

    // ── New lifecycle timestamps ──────────────────────────────────────────
    await queryRunner.query(`
      ALTER TABLE freight.warehouse_inventory
      ADD COLUMN IF NOT EXISTS stored_at TIMESTAMPTZ NULL,
      ADD COLUMN IF NOT EXISTS reserved_at TIMESTAMPTZ NULL,
      ADD COLUMN IF NOT EXISTS loaded_at TIMESTAMPTZ NULL,
      ADD COLUMN IF NOT EXISTS dispatched_at TIMESTAMPTZ NULL;
    `);

    // booking_id becomes nullable (inventory can exist before booking linkage).
    await queryRunner.query(`
      ALTER TABLE freight.warehouse_inventory ALTER COLUMN booking_id DROP NOT NULL;
    `);

    // ── Movement history ──────────────────────────────────────────────────
    await queryRunner.query(`
      CREATE TABLE IF NOT EXISTS freight.warehouse_inventory_movement (
        id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
        inventory_id UUID NOT NULL REFERENCES freight.warehouse_inventory(id) ON DELETE CASCADE,
        from_warehouse_id UUID NOT NULL,
        from_yard_id UUID NOT NULL,
        from_zone_id UUID NOT NULL,
        to_warehouse_id UUID NOT NULL,
        to_yard_id UUID NOT NULL,
        to_zone_id UUID NOT NULL,
        remarks TEXT NULL,
        moved_by VARCHAR(120) NULL,
        moved_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_warehouse_inventory_movement_inventory_id
      ON freight.warehouse_inventory_movement(inventory_id);
    `);

    // ── Activity log ──────────────────────────────────────────────────────
    await queryRunner.query(`
      CREATE TABLE IF NOT EXISTS freight.warehouse_activity_log (
        id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
        inventory_id UUID NULL,
        warehouse_id UUID NULL,
        activity_type VARCHAR(40) NOT NULL,
        description TEXT NULL,
        performed_by VARCHAR(120) NULL,
        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_warehouse_activity_log_inventory_id
      ON freight.warehouse_activity_log(inventory_id);
    `);
    await queryRunner.query(`
      CREATE INDEX IF NOT EXISTS idx_warehouse_activity_log_warehouse_id
      ON freight.warehouse_activity_log(warehouse_id);
    `);
    await queryRunner.query(`
      CREATE INDEX IF NOT EXISTS idx_warehouse_activity_log_activity_type
      ON freight.warehouse_activity_log(activity_type);
    `);
  }

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

    await queryRunner.query(`
      ALTER TABLE freight.warehouse_inventory
      DROP COLUMN IF EXISTS stored_at,
      DROP COLUMN IF EXISTS reserved_at,
      DROP COLUMN IF EXISTS loaded_at,
      DROP COLUMN IF EXISTS dispatched_at;
    `);
    await queryRunner.query(`
      ALTER TABLE freight.warehouse_inventory ALTER COLUMN status SET DEFAULT 'RECEIVED';
    `);

    for (const table of ['warehouses', 'warehouse_yards', 'warehouse_zones']) {
      await queryRunner.query(`
        ALTER TABLE freight.${table}
        DROP COLUMN IF EXISTS max_weight,
        DROP COLUMN IF EXISTS max_volume,
        DROP COLUMN IF EXISTS current_volume;
      `);
    }
  }
}
