import { existsSync, readFileSync } from 'node:fs';
import { join } from 'node:path';

const migrationPath = join(
  process.cwd(),
  'prisma',
  'migrations',
  '20260703000000_v22_partitioned_domain_schema',
  'migration.sql',
);

function readMigrationSql() {
  if (!existsSync(migrationPath)) {
    throw new Error(`Missing V2.2 migration: ${migrationPath}`);
  }
  return readFileSync(migrationPath, 'utf8');
}

function expectPartitionedTable(
  sql: string,
  table: string,
  method: 'HASH' | 'RANGE',
  key: string,
  primaryKey: string[],
) {
  const quotedPrimaryKey = primaryKey.map((column) => `"${column}"`).join(', ');
  expect(sql).toMatch(
    new RegExp(
      `CREATE TABLE "${table}"[\\s\\S]*CONSTRAINT "${table}_pkey" PRIMARY KEY \\(${quotedPrimaryKey}\\)[\\s\\S]*PARTITION BY ${method} \\("${key}"\\);`,
    ),
  );
}

function expectHashPartitions(sql: string, table: string, count: number) {
  const matches = sql.match(
    new RegExp(`PARTITION OF "${table}" FOR VALUES WITH \\(MODULUS ${count}, REMAINDER`, 'g'),
  );
  expect(matches).toHaveLength(count);
}

describe('V2.2 partitioned domain schema migration', () => {
  it('keeps every hash partitioned business table primary key anchored by the partition key', () => {
    const sql = readMigrationSql();

    expectPartitionedTable(sql, 'requirements', 'HASH', 'product_id', ['id', 'product_id']);
    expectPartitionedTable(sql, 'dev_tasks', 'HASH', 'version_id', ['id', 'version_id']);
    expectPartitionedTable(sql, 'test_cases', 'HASH', 'version_id', ['id', 'version_id']);
    expectPartitionedTable(sql, 'bugs', 'HASH', 'version_id', ['id', 'version_id']);

    expectHashPartitions(sql, 'requirements', 16);
    expectHashPartitions(sql, 'dev_tasks', 16);
    expectHashPartitions(sql, 'test_cases', 16);
    expectHashPartitions(sql, 'bugs', 16);
  });

  it('includes partition keys in business unique constraints', () => {
    const sql = readMigrationSql();

    expect(sql).toMatch(/CONSTRAINT "requirements_product_id_code_key" UNIQUE \("product_id", "code"\)/);
    expect(sql).toMatch(/CONSTRAINT "dev_tasks_version_id_code_key" UNIQUE \("version_id", "code"\)/);
    expect(sql).toMatch(/CONSTRAINT "test_cases_version_id_code_key" UNIQUE \("version_id", "code"\)/);
    expect(sql).toMatch(/CONSTRAINT "bugs_version_id_code_key" UNIQUE \("version_id", "code"\)/);
  });

  it('uses composite foreign keys when a referenced table is partitioned', () => {
    const sql = readMigrationSql();

    expect(sql).toMatch(
      /FOREIGN KEY \("requirement_id", "requirement_product_id"\) REFERENCES "requirements"\("id", "product_id"\)/,
    );
    expect(sql).toMatch(
      /FOREIGN KEY \("test_case_id", "test_case_version_id"\) REFERENCES "test_cases"\("id", "version_id"\)/,
    );
  });

  it('range partitions append-only evidence and snapshot tables by created_at', () => {
    const sql = readMigrationSql();

    expectPartitionedTable(sql, 'work_activities', 'RANGE', 'created_at', ['id', 'created_at']);
    expectPartitionedTable(sql, 'task_worklogs', 'RANGE', 'created_at', ['id', 'created_at']);
    expectPartitionedTable(sql, 'overtime_records', 'RANGE', 'created_at', ['id', 'created_at']);
    expectPartitionedTable(sql, 'xiaobao_risk_snapshots', 'RANGE', 'created_at', ['id', 'created_at']);
    expectPartitionedTable(sql, 'ai_logs', 'RANGE', 'created_at', ['id', 'created_at']);

    for (const table of [
      'work_activities',
      'task_worklogs',
      'overtime_records',
      'xiaobao_risk_snapshots',
      'ai_logs',
    ]) {
      expect(sql).toMatch(new RegExp(`CREATE TABLE "${table}_default" PARTITION OF "${table}" DEFAULT;`));
    }
  });

  it('keeps Xiaobao current summaries as one row per version instead of partitioned history', () => {
    const sql = readMigrationSql();

    expect(sql).toMatch(
      /CREATE TABLE "xiaobao_risk_summaries"[\s\S]*CONSTRAINT "xiaobao_risk_summaries_pkey" PRIMARY KEY \("version_id"\)/,
    );
    expect(sql).not.toMatch(/CREATE TABLE "xiaobao_risk_summaries"[\s\S]*PARTITION BY/);
  });
});
