import { MigrationInterface, QueryRunner } from 'typeorm';

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

  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`
      CREATE TABLE IF NOT EXISTS freight.warehouses (
        id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
        name VARCHAR(160) NOT NULL,
        code VARCHAR(40) NOT NULL UNIQUE,
        type VARCHAR(32) NOT NULL,
        station_id UUID NULL,
        location_name VARCHAR(200) NULL,
        capacity_weight NUMERIC(14,3) NULL,
        capacity_containers INT NULL,
        current_weight NUMERIC(14,3) NOT NULL DEFAULT 0,
        current_containers INT NOT NULL DEFAULT 0,
        status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
        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
      );
    `);

    await queryRunner.query(`
      CREATE TABLE IF NOT EXISTS freight.warehouse_yards (
        id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
        warehouse_id UUID NOT NULL REFERENCES freight.warehouses(id) ON DELETE CASCADE,
        name VARCHAR(160) NOT NULL,
        code VARCHAR(40) NOT NULL,
        type VARCHAR(32) NOT NULL,
        capacity_weight NUMERIC(14,3) NULL,
        capacity_containers INT NULL,
        current_weight NUMERIC(14,3) NOT NULL DEFAULT 0,
        current_containers INT NOT NULL DEFAULT 0,
        status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
        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,
        CONSTRAINT uq_warehouse_yards_code UNIQUE (warehouse_id, code)
      );
    `);

    await queryRunner.query(`
      CREATE TABLE IF NOT EXISTS freight.warehouse_zones (
        id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
        yard_id UUID NOT NULL REFERENCES freight.warehouse_yards(id) ON DELETE CASCADE,
        name VARCHAR(160) NOT NULL,
        code VARCHAR(40) NOT NULL,
        type VARCHAR(32) NOT NULL,
        capacity_weight NUMERIC(14,3) NULL,
        capacity_containers INT NULL,
        current_weight NUMERIC(14,3) NOT NULL DEFAULT 0,
        current_containers INT NOT NULL DEFAULT 0,
        status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
        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,
        CONSTRAINT uq_warehouse_zones_code UNIQUE (yard_id, code)
      );
    `);

    await queryRunner.query(`
      CREATE TABLE IF NOT EXISTS freight.warehouse_inventory (
        id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
        warehouse_id UUID NOT NULL REFERENCES freight.warehouses(id),
        yard_id UUID NOT NULL REFERENCES freight.warehouse_yards(id),
        zone_id UUID NOT NULL REFERENCES freight.warehouse_zones(id),
        booking_id UUID NOT NULL,
        cargo_id UUID NULL,
        container_id UUID NULL,
        goods_id UUID NULL,
        quantity NUMERIC(12,3) NOT NULL DEFAULT 0,
        weight NUMERIC(14,3) NOT NULL DEFAULT 0,
        volume NUMERIC(12,3) NULL,
        status VARCHAR(32) NOT NULL DEFAULT 'ARRIVED_AT_WAREHOUSE',
        arrived_at TIMESTAMPTZ NULL,
        inspected_at TIMESTAMPTZ NULL,
        ready_for_loading_at TIMESTAMPTZ NULL,
        notes TEXT NULL,
        created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
        updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
        deleted_at TIMESTAMPTZ NULL
      );
    `);

    const indexes: Array<[string, string, string]> = [
      ['idx_warehouses_type', 'warehouses', 'type'],
      ['idx_warehouses_status', 'warehouses', 'status'],
      ['idx_warehouses_station_id', 'warehouses', 'station_id'],
      ['idx_warehouse_yards_warehouse_id', 'warehouse_yards', 'warehouse_id'],
      ['idx_warehouse_yards_type', 'warehouse_yards', 'type'],
      ['idx_warehouse_yards_status', 'warehouse_yards', 'status'],
      ['idx_warehouse_zones_yard_id', 'warehouse_zones', 'yard_id'],
      ['idx_warehouse_zones_type', 'warehouse_zones', 'type'],
      ['idx_warehouse_zones_status', 'warehouse_zones', 'status'],
      ['idx_warehouse_inventory_warehouse_id', 'warehouse_inventory', 'warehouse_id'],
      ['idx_warehouse_inventory_yard_id', 'warehouse_inventory', 'yard_id'],
      ['idx_warehouse_inventory_zone_id', 'warehouse_inventory', 'zone_id'],
      ['idx_warehouse_inventory_booking_id', 'warehouse_inventory', 'booking_id'],
      ['idx_warehouse_inventory_cargo_id', 'warehouse_inventory', 'cargo_id'],
      ['idx_warehouse_inventory_container_id', 'warehouse_inventory', 'container_id'],
      ['idx_warehouse_inventory_goods_id', 'warehouse_inventory', 'goods_id'],
      ['idx_warehouse_inventory_status', 'warehouse_inventory', 'status'],
    ];

    for (const [indexName, table, column] of indexes) {
      await queryRunner.query(
        `CREATE INDEX IF NOT EXISTS ${indexName} ON freight.${table}(${column});`,
      );
    }
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`DROP TABLE IF EXISTS freight.warehouse_inventory;`);
    await queryRunner.query(`DROP TABLE IF EXISTS freight.warehouse_zones;`);
    await queryRunner.query(`DROP TABLE IF EXISTS freight.warehouse_yards;`);
    await queryRunner.query(`DROP TABLE IF EXISTS freight.warehouses;`);
  }
}
