import { runSchemaMigrations, } from "../../../db/migration.js";
import { cdcSchema } from "../../../types/shards.js";
import { createReplicationStateTable, setupCDCTables, } from "./tables.js";
async function migrateFromLegacySchemas(lc, db, newSchema, ...legacy) {
    const rows = await db `
    SELECT nspname FROM pg_namespace 
      WHERE nspname IN ${db([newSchema, ...legacy])}`.values();
    // oxlint-disable-next-line unicorn/prefer-set-has -- Small collection, array is more appropriate
    const names = rows.flat();
    if (names.includes(newSchema)) {
        return; // already migrated
    }
    for (const schema of legacy) {
        if (names.includes(schema)) {
            lc.info?.(`Migrating ${schema} to ${newSchema}`);
            await db `ALTER SCHEMA ${db(schema)} RENAME TO ${db(newSchema)}`;
            break;
        }
    }
}
export async function initChangeStreamerSchema(log, db, shard) {
    const schema = cdcSchema(shard);
    const { appID } = shard;
    await migrateFromLegacySchemas(log, db, schema, appID === 'zero' ? `cdc_0` : `cdc_${appID}`, 'cdc');
    const setupMigration = {
        migrateSchema: (lc, tx) => setupCDCTables(lc, tx, shard),
        minSafeVersion: 1,
    };
    async function migrateV1toV2(_, db) {
        await db `
    ALTER TABLE ${db(schema)}."replicationConfig" ADD "resetRequired" BOOL`;
    }
    const migrateV2ToV3 = {
        migrateSchema: async (_, db) => {
            await db.unsafe(createReplicationStateTable(shard));
        },
        migrateData: async (_, db) => {
            const lastWatermark = await getLastWatermarkV2(db, shard);
            const replicationState = { lastWatermark };
            await db `
      TRUNCATE TABLE ${db(schema)}."replicationState"`;
            await db `
      INSERT INTO ${db(schema)}."replicationState" ${db(replicationState)}`;
        },
    };
    const migrateV3ToV4 = {
        migrateSchema: async (_, db) => {
            await db `
      ALTER TABLE ${db(schema)}."changeLog" ALTER "change" TYPE JSON;
      `;
        },
    };
    const migrateV4ToV5 = {
        migrateSchema: async (_, db) => {
            await db `
      ALTER TABLE ${db(schema)}."replicationState" ADD "ownerAddress" TEXT;
      `;
        },
    };
    const schemaVersionMigrationMap = {
        2: { migrateSchema: migrateV1toV2 },
        3: migrateV2ToV3,
        4: migrateV3ToV4,
        5: migrateV4ToV5,
    };
    await runSchemaMigrations(log, 'change-streamer', schema, db, setupMigration, schemaVersionMigrationMap);
}
export async function getLastWatermarkV2(db, shard) {
    const schema = cdcSchema(shard);
    const [{ max }] = await db `
    SELECT MAX(watermark) as max FROM ${db(schema)}."changeLog"`;
    if (max !== null) {
        return max;
    }
    // The changeLog is only empty if nothing has been synced since initial-sync.
    // In this case, the last watermark is the replicaVersion.
    const [{ replicaVersion }] = await db `
    SELECT "replicaVersion" FROM ${db(schema)}."replicationConfig"
    `;
    return replicaVersion;
}
//# sourceMappingURL=init.js.map