import { MigrationInterface, QueryRunner } from 'typeorm';

const SHORT_CODE_CHARS = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';

function randomShortCode(): string {
  let s = '';
  for (let i = 0; i < 8; i++) {
    s += SHORT_CODE_CHARS[Math.floor(Math.random() * SHORT_CODE_CHARS.length)];
  }
  return s;
}

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

  public async up(queryRunner: QueryRunner): Promise<void> {
    const hasColumn = await queryRunner.query(`
      SELECT 1 FROM information_schema.columns
      WHERE table_schema = 'public' AND table_name = 'builds' AND column_name = 'short_code'
    `);
    if (!hasColumn?.length) {
      await queryRunner.query(`
        ALTER TABLE "builds"
        ADD COLUMN "short_code" character varying(8)
      `);
    }
    const rowsToFill = await queryRunner.query(`
      SELECT id FROM "builds" WHERE "short_code" IS NULL
    `);
    const used = new Set<string>();
    for (const row of rowsToFill || []) {
      let code: string;
      do {
        code = randomShortCode();
      } while (used.has(code));
      used.add(code);
      await queryRunner.query(
        `UPDATE "builds" SET "short_code" = $1 WHERE "id" = $2`,
        [code, row.id],
      );
    }
    if (rowsToFill?.length > 0 || !hasColumn?.length) {
      await queryRunner.query(`
        ALTER TABLE "builds"
        ALTER COLUMN "short_code" SET NOT NULL
      `).catch(() => {});
      await queryRunner.query(`
        CREATE UNIQUE INDEX "UQ_builds_short_code" ON "builds" ("short_code")
      `).catch(() => {});
    }
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(`DROP INDEX IF EXISTS "UQ_builds_short_code"`);
    await queryRunner.query(`ALTER TABLE "builds" DROP COLUMN IF EXISTS "short_code"`);
  }
}
