import { MigrationInterface, QueryRunner } from 'typeorm';

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

  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`
      CREATE TABLE IF NOT EXISTS freight.customers (
        id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
        user_id UUID NOT NULL,
        first_name VARCHAR(100) NOT NULL,
        last_name VARCHAR(100) NOT NULL,
        email VARCHAR(150) NOT NULL UNIQUE,
        phone VARCHAR(20) NOT NULL,
        company_name VARCHAR(200) NOT NULL,
        company_email VARCHAR(150) NOT NULL,
        company_phone VARCHAR(20) NOT NULL,
        company_location VARCHAR(100) NOT NULL,
        company_address TEXT NOT NULL,
        customer_type VARCHAR(32),
        status VARCHAR(32),
        contact_person_name VARCHAR(100) NOT NULL,
        contact_person_phone VARCHAR(20) NOT NULL,
        tin_number VARCHAR(10) NOT NULL UNIQUE,
        vat_number VARCHAR(50),
        fan_number VARCHAR(16) NOT NULL UNIQUE,
        general_manager_name VARCHAR(100) NOT NULL,
        general_manager_email VARCHAR(150) NOT NULL,
        general_manager_phone VARCHAR(20) NOT NULL,
        poa_name VARCHAR(100),
        poa_phone VARCHAR(20),
        poa_address TEXT,
        poa_email VARCHAR(150),
        poa_location VARCHAR(100),
        notes TEXT,
        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_freight_customers_email"
        ON freight.customers (email);
    `);
   // await queryRunner.query(`
     // CREATE INDEX IF NOT EXISTS "IDX_freight_customers_user_id"
     //   ON freight.customers (user_id);
    //`);

    // Copy rows from public.customers when that legacy table exists
    await queryRunner.query(`
      DO $$
      DECLARE
        has_public boolean;
        has_user_id boolean;
        has_userid boolean;
      BEGIN
        SELECT EXISTS (
          SELECT 1 FROM information_schema.tables
          WHERE table_schema = 'public' AND table_name = 'customers'
        ) INTO has_public;

        IF NOT has_public THEN
          RETURN;
        END IF;

        SELECT EXISTS (
          SELECT 1 FROM information_schema.columns
          WHERE table_schema = 'public' AND table_name = 'customers' AND column_name = 'user_id'
        ) INTO has_user_id;

        SELECT EXISTS (
          SELECT 1 FROM information_schema.columns
          WHERE table_schema = 'public' AND table_name = 'customers' AND column_name = 'userid'
        ) INTO has_userid;

        IF has_user_id THEN
          INSERT INTO freight.customers (
            id, user_id, first_name, last_name, email, phone,
            company_name, company_email, company_phone, company_location, company_address,
            contact_person_name, contact_person_phone, tin_number, vat_number, fan_number,
            general_manager_name, general_manager_email, general_manager_phone,
            poa_name, poa_phone, poa_address, poa_email, poa_location, notes,
            created_at, updated_at
          )
          SELECT
            id, user_id, first_name, last_name, email, phone,
            company_name, company_email, company_phone, company_location, company_address,
            contact_person_name, contact_person_phone, tin_number, vat_number, fan_number,
            general_manager_name, general_manager_email, general_manager_phone,
            poa_name, poa_phone, poa_address, poa_email, poa_location, notes,
            COALESCE(created_at, now()), COALESCE(updated_at, now())
          FROM public.customers
          ON CONFLICT (id) DO NOTHING;
        ELSIF has_userid THEN
          INSERT INTO freight.customers (
            id, user_id, first_name, last_name, email, phone,
            company_name, company_email, company_phone, company_location, company_address,
            contact_person_name, contact_person_phone, tin_number, vat_number, fan_number,
            general_manager_name, general_manager_email, general_manager_phone,
            poa_name, poa_phone, poa_address, poa_email, poa_location, notes,
            created_at, updated_at
          )
          SELECT
            id, userid, firstname, lastname, email, phone,
            companyname, companyemail, companyphone, companylocation, companyaddress,
            contactpersonname, contactpersonphone, tinnumber, vatnumber, fannumber,
            generalmanagername, generalmanageremail, generalmanagerphone,
            poaname, poaphone, poaaddress, poaemail, poalocation, notes,
            COALESCE("createdAt", now()), COALESCE("updatedAt", now())
          FROM public.customers
          ON CONFLICT (id) DO NOTHING;
        END IF;
      END $$;
    `);

    await queryRunner.query(`
      ALTER TABLE freight.bookings
        DROP CONSTRAINT IF EXISTS "FK_bookings_customer_id";
    `);

    await queryRunner.query(`
      DELETE FROM freight.booking_cargo_modifier bcm
      USING freight.bookings b
      WHERE bcm.booking_id = b.id
        AND NOT EXISTS (SELECT 1 FROM freight.customers c WHERE c.id = b.customer_id);
    `);
    await queryRunner.query(`
      DELETE FROM freight.booking_approval_step bas
      USING freight.bookings b
      WHERE bas.booking_id = b.id
        AND NOT EXISTS (SELECT 1 FROM freight.customers c WHERE c.id = b.customer_id);
    `);
    await queryRunner.query(`
      DELETE FROM freight.booking_rate_snapshot brs
      USING freight.bookings b
      WHERE brs.booking_id = b.id
        AND NOT EXISTS (SELECT 1 FROM freight.customers c WHERE c.id = b.customer_id);
    `);
    await queryRunner.query(`
      DELETE FROM freight.booking_container bc
      USING freight.bookings b
      WHERE bc.booking_id = b.id
        AND NOT EXISTS (SELECT 1 FROM freight.customers c WHERE c.id = b.customer_id);
    `);
    await queryRunner.query(`
      DELETE FROM freight.bookings b
      WHERE NOT EXISTS (SELECT 1 FROM freight.customers c WHERE c.id = b.customer_id);
    `);

    await queryRunner.query(`
      DO $$ BEGIN
        ALTER TABLE freight.bookings
          ADD CONSTRAINT "FK_bookings_customer_id"
          FOREIGN KEY (customer_id)
          REFERENCES freight.customers(id)
          ON DELETE RESTRICT;
      EXCEPTION
        WHEN duplicate_object THEN NULL;
      END $$;
    `);
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`
      ALTER TABLE freight.bookings
        DROP CONSTRAINT IF EXISTS "FK_bookings_customer_id";
    `);

    await queryRunner.query(`
      DO $$ BEGIN
        ALTER TABLE freight.bookings
          ADD CONSTRAINT "FK_bookings_customer_id"
          FOREIGN KEY (customer_id)
          REFERENCES public.customers(id)
          ON DELETE RESTRICT;
      EXCEPTION
        WHEN duplicate_object THEN NULL;
      END $$;
    `);

    await queryRunner.query(`DROP TABLE IF EXISTS freight.customers CASCADE;`);
  }
}
