import { MigrationInterface, QueryRunner } from "typeorm";

/**
 * Government bookings now bill to a real seeded government company + an explicit
 * importer/exporter profile, instead of carrying a null company + free-text
 * institution. This migration:
 *
 *   1. Adds `companies.kind` (commercial | government).
 *   2. Seeds the Ethiopian government entities + their importer/exporter
 *      profiles (mirrors src/seed/data/gov-companies.data.ts — keep in sync).
 *   3. Backfills every booking with a NULL company_id / company_profile_id so
 *      the NOT NULL constraints below can be applied:
 *        - NULL company_id  → the default government company.
 *        - NULL company_profile_id → the company's profile matching the booking
 *          trade direction; else any profile of the company; else the default
 *          government importer profile.
 *   4. Enforces NOT NULL on bookings.company_id and bookings.company_profile_id.
 */
export class AddCompanyKindAndGovBookingLinks1821000000003
  implements MigrationInterface
{
  name = "AddCompanyKindAndGovBookingLinks1821000000003";

  // Mirrors src/seed/data/gov-companies.data.ts
  private readonly govCompanies = [
    { id: "0a1b0001-0000-4000-8000-000000000001", name: "Federal Government of Ethiopia", tin: "0000000001", email: "procurement@gov.et", phone: "+251111000001", im: "0b1c0001-0000-4000-8000-000000000001", ex: "0b1c0001-0000-4000-8000-000000000002", imRef: "IM-90001", exRef: "EX-90001" },
    { id: "0a1b0002-0000-4000-8000-000000000002", name: "Ministry of National Defense", tin: "0000000002", email: "logistics@mod.gov.et", phone: "+251111000002", im: "0b1c0002-0000-4000-8000-000000000001", ex: "0b1c0002-0000-4000-8000-000000000002", imRef: "IM-90002", exRef: "EX-90002" },
    { id: "0a1b0003-0000-4000-8000-000000000003", name: "Ethiopian Roads Administration", tin: "0000000003", email: "supply@era.gov.et", phone: "+251111000003", im: "0b1c0003-0000-4000-8000-000000000001", ex: "0b1c0003-0000-4000-8000-000000000002", imRef: "IM-90003", exRef: "EX-90003" },
    { id: "0a1b0004-0000-4000-8000-000000000004", name: "Ministry of Agriculture", tin: "0000000004", email: "imports@moa.gov.et", phone: "+251111000004", im: "0b1c0004-0000-4000-8000-000000000001", ex: "0b1c0004-0000-4000-8000-000000000002", imRef: "IM-90004", exRef: "EX-90004" },
    { id: "0a1b0005-0000-4000-8000-000000000005", name: "Ministry of Trade and Regional Integration", tin: "0000000005", email: "trade@motri.gov.et", phone: "+251111000005", im: "0b1c0005-0000-4000-8000-000000000001", ex: "0b1c0005-0000-4000-8000-000000000002", imRef: "IM-90005", exRef: "EX-90005" },
    { id: "0a1b0006-0000-4000-8000-000000000006", name: "Ethiopian Disaster Risk Management Commission", tin: "0000000006", email: "relief@edrmc.gov.et", phone: "+251111000006", im: "0b1c0006-0000-4000-8000-000000000001", ex: "0b1c0006-0000-4000-8000-000000000002", imRef: "IM-90006", exRef: "EX-90006" },
  ];

  private get defaultCompanyId(): string {
    return this.govCompanies[0].id;
  }
  private get defaultImporterProfileId(): string {
    return this.govCompanies[0].im;
  }

  public async up(queryRunner: QueryRunner): Promise<void> {
    // 1. kind column
    await queryRunner.query(
      `ALTER TABLE "freight"."companies" ADD COLUMN IF NOT EXISTS "kind" varchar(20) NOT NULL DEFAULT 'commercial'`,
    );
    await queryRunner.query(
      `CREATE INDEX IF NOT EXISTS "IDX_companies_kind" ON "freight"."companies" ("kind")`,
    );

    // 2. seed government companies + importer/exporter profiles (idempotent)
    for (const g of this.govCompanies) {
      await queryRunner.query(
        `INSERT INTO "freight"."companies" ("id", "name", "type", "kind", "status", "tin", "country", "email", "phone")
         VALUES ($1, $2, 'customer', 'government', 'active', $3, 'Ethiopia', $4, $5)
         ON CONFLICT ("id") DO NOTHING`,
        [g.id, g.name, g.tin, g.email, g.phone],
      );
      await queryRunner.query(
        `INSERT INTO "freight"."company_profiles" ("id", "company_id", "type", "reference", "status")
         VALUES ($1, $2, 'importer', $3, 'active'), ($4, $2, 'exporter', $5, 'active')
         ON CONFLICT ("id") DO NOTHING`,
        [g.im, g.id, g.imRef, g.ex, g.exRef],
      );
    }

    // 3a. backfill NULL company_id → default government company
    await queryRunner.query(
      `UPDATE "freight"."bookings" SET "company_id" = $1 WHERE "company_id" IS NULL`,
      [this.defaultCompanyId],
    );

    // 3b. backfill NULL company_profile_id → profile matching trade direction
    await queryRunner.query(
      `UPDATE "freight"."bookings" b
         SET "company_profile_id" = cp."id"
         FROM "freight"."company_profiles" cp
        WHERE b."company_profile_id" IS NULL
          AND cp."company_id" = b."company_id"
          AND cp."deleted_at" IS NULL
          AND cp."type" = CASE b."trade_direction"
                            WHEN 'IMPORT' THEN 'importer'
                            WHEN 'EXPORT' THEN 'exporter'
                            ELSE NULL END`,
    );

    // 3c. fallback → any profile of the booking's company
    await queryRunner.query(
      `UPDATE "freight"."bookings" b
         SET "company_profile_id" = (
           SELECT cp."id" FROM "freight"."company_profiles" cp
            WHERE cp."company_id" = b."company_id" AND cp."deleted_at" IS NULL
            ORDER BY cp."created_at" ASC LIMIT 1)
        WHERE b."company_profile_id" IS NULL
          AND EXISTS (
            SELECT 1 FROM "freight"."company_profiles" cp
             WHERE cp."company_id" = b."company_id" AND cp."deleted_at" IS NULL)`,
    );

    // 3d. final fallback → default government importer profile
    await queryRunner.query(
      `UPDATE "freight"."bookings" SET "company_profile_id" = $1 WHERE "company_profile_id" IS NULL`,
      [this.defaultImporterProfileId],
    );

    // 4. enforce NOT NULL
    await queryRunner.query(
      `ALTER TABLE "freight"."bookings" ALTER COLUMN "company_id" SET NOT NULL`,
    );
    await queryRunner.query(
      `ALTER TABLE "freight"."bookings" ALTER COLUMN "company_profile_id" SET NOT NULL`,
    );
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(
      `ALTER TABLE "freight"."bookings" ALTER COLUMN "company_profile_id" DROP NOT NULL`,
    );
    await queryRunner.query(
      `ALTER TABLE "freight"."bookings" ALTER COLUMN "company_id" DROP NOT NULL`,
    );
    await queryRunner.query(
      `DROP INDEX IF EXISTS "freight"."IDX_companies_kind"`,
    );
    await queryRunner.query(
      `ALTER TABLE "freight"."companies" DROP COLUMN IF EXISTS "kind"`,
    );
    // Seeded government rows are intentionally left in place.
  }
}
