import { cvrSchema } from "../../../types/shards.js";
import { runSchemaMigrations } from "../../../db/migration.js";
import { createRowsVersionTable, setupCVRTables } from "./cvr.js";
//#region ../zero-cache/src/services/view-syncer/schema/init.ts
async function initViewSyncerSchema(log, db, shard) {
	const schema = cvrSchema(shard);
	const setupMigration = {
		migrateSchema: (lc, tx) => setupCVRTables(lc, tx, shard),
		minSafeVersion: 1
	};
	const migrateV1toV2 = { migrateSchema: async (_, tx) => {
		await tx`ALTER TABLE ${tx(schema)}.instances ADD "replicaVersion" TEXT`;
	} };
	const migrateV2ToV3 = {
		migrateSchema: async (_, tx) => {
			await tx.unsafe(createRowsVersionTable(shard));
		},
		migrateData: async (lc, tx) => {
			const pending = [];
			for await (const versions of tx`
      SELECT "clientGroupID", "version" FROM ${tx(schema)}.instances`.cursor(5e3)) for (const version of versions) pending.push(tx`INSERT INTO ${tx(schema)}."rowsVersion" ${tx(version)} 
               ON CONFLICT ("clientGroupID")
               DO UPDATE SET ${tx(version)}`.execute());
			lc.info?.(`initializing rowsVersion for ${pending.length} cvrs`);
			await Promise.all(pending);
		}
	};
	const migrateV3ToV4 = { migrateSchema: async (_, tx) => {
		await tx`ALTER TABLE ${tx(schema)}.instances ADD "owner" TEXT`;
		await tx`ALTER TABLE ${tx(schema)}.instances ADD "grantedAt" TIMESTAMPTZ`;
	} };
	const migrateV5ToV6 = { migrateSchema: async (_, tx) => {
		await tx`
      ALTER TABLE ${tx(schema)}."rows"
        DROP CONSTRAINT fk_rows_client_group`;
		await tx`
      ALTER TABLE ${tx(schema)}."rowsVersion"
        DROP CONSTRAINT fk_rows_version_client_group`;
	} };
	const migrateV6ToV7 = { migrateSchema: async (_, tx) => {
		await tx`ALTER TABLE ${tx(schema)}.desires ADD "expiresAt" TIMESTAMPTZ`;
		await tx`ALTER TABLE ${tx(schema)}.desires ADD "inactivatedAt" TIMESTAMPTZ`;
		await tx`ALTER TABLE ${tx(schema)}.desires ADD "ttl" INTERVAL`;
		await tx`CREATE INDEX desires_expires_at ON ${tx(schema)}.desires ("expiresAt")`;
		await tx`CREATE INDEX desires_inactivated_at ON ${tx(schema)}.desires ("inactivatedAt")`;
	} };
	const migrateV7ToV8 = { migrateSchema: async (_, tx) => {
		await tx`ALTER TABLE ${tx(schema)}."desires" DROP CONSTRAINT fk_desires_client`;
	} };
	const migrateV8ToV9 = { migrateSchema: async (_, tx) => {
		await tx`ALTER TABLE ${tx(schema)}.instances ADD "clientSchema" JSONB`;
	} };
	const migrateV9ToV10 = { migrateSchema: async (_, tx) => {
		await tx`ALTER TABLE ${tx(schema)}.queries ADD "queryName" TEXT`;
		await tx`ALTER TABLE ${tx(schema)}.queries ADD "queryArgs" JSONB`;
		await tx`ALTER TABLE ${tx(schema)}.queries ALTER COLUMN "clientAST" DROP NOT NULL`;
	} };
	const migrateV10ToV11 = { migrateSchema: async (_, tx) => {
		await tx`DROP INDEX IF EXISTS ${tx(schema)}.desires_expires_at`;
		await tx`ALTER TABLE ${tx(schema)}.desires DROP COLUMN "expiresAt"`;
		await tx`DROP INDEX IF EXISTS ${tx(schema)}.client_patch_version`;
		await tx`ALTER TABLE ${tx(schema)}.clients DROP COLUMN "patchVersion"`;
		await tx`ALTER TABLE ${tx(schema)}.clients DROP COLUMN "deleted"`;
	} };
	const migratedV11ToV12 = { migrateSchema: async (_, tx) => {
		await tx`ALTER TABLE ${tx(schema)}.queries ALTER COLUMN "queryArgs" TYPE JSON USING "queryArgs"::JSON`;
	} };
	const migratedV12ToV13 = { migrateSchema: async (_, tx) => {
		await tx`ALTER TABLE ${tx(schema)}.instances ADD COLUMN "ttlClock" DOUBLE PRECISION NOT NULL DEFAULT 0`;
	} };
	const migratedV13ToV14 = { migrateSchema: async (_, sql) => {
		await sql`
        CREATE INDEX instances_last_active ON ${sql(schema)}.instances ("lastActive");
      `;
		for (const [table, reference] of [
			["clients", "instances"],
			["queries", "instances"],
			["rows", "rowsVersion"]
		]) {
			const constraint = sql(`fk_${table}_client_group`);
			await sql`
          ALTER TABLE ${sql(schema)}.${sql(table)} DROP CONSTRAINT IF EXISTS ${constraint}`;
			await sql`
          ALTER TABLE ${sql(schema)}.${sql(table)} ADD CONSTRAINT ${constraint}
            FOREIGN KEY("clientGroupID")
            REFERENCES ${sql(schema)}.${sql(reference)} ("clientGroupID")
            ON DELETE CASCADE;
        `;
		}
	} };
	const migratedV14ToV15 = {
		migrateSchema: async (_, sql) => {
			await sql`ALTER TABLE ${sql(schema)}.desires 
        ADD COLUMN "inactivatedAtMs" DOUBLE PRECISION`;
			await sql`ALTER TABLE ${sql(schema)}.desires 
        ADD COLUMN "ttlMs" DOUBLE PRECISION`;
		},
		migrateData: async (lc, sql) => {
			lc.info?.("Migrating desires.inactivatedAt to inactivatedAtMs and ttl to ttlMs");
			await sql`
        UPDATE ${sql(schema)}.desires
        SET "inactivatedAtMs" = EXTRACT(EPOCH FROM "inactivatedAt") * 1000,
            "ttlMs" = EXTRACT(EPOCH FROM "ttl") * 1000
      `;
		}
	};
	const migratedV15ToV16 = {
		migrateSchema: async (_, sql) => {
			await sql`ALTER TABLE ${sql(schema)}.instances ADD COLUMN "profileID" TEXT`;
			await sql`ALTER TABLE ${sql(schema)}.instances ADD COLUMN "deleted" BOOL DEFAULT FALSE`;
			await sql`
        DROP INDEX IF EXISTS ${sql(schema)}.instances_last_active`;
			await sql`
        CREATE INDEX instances_last_active ON ${sql(schema)}.instances ("lastActive")
          WHERE NOT "deleted"`;
			await sql`
        CREATE INDEX tombstones_last_active ON ${sql(schema)}.instances ("lastActive")
          WHERE "deleted"`;
			await sql`
        CREATE INDEX profile_ids_last_active ON ${sql(schema)}.instances ("lastActive", "profileID")
          WHERE "profileID" IS NOT NULL`;
		},
		migrateData: async (lc, sql) => {
			lc.info?.("Backfilling instance.profileIDs");
			await sql`
        UPDATE ${sql(schema)}.instances
        SET "profileID" = 'cg' || "clientGroupID"
        WHERE "profileID" IS NULL
      `;
		}
	};
	const schemaVersionMigrationMap = {
		2: migrateV1toV2,
		3: migrateV2ToV3,
		4: migrateV3ToV4,
		5: { minSafeVersion: 3 },
		6: migrateV5ToV6,
		7: migrateV6ToV7,
		8: migrateV7ToV8,
		9: migrateV8ToV9,
		10: migrateV9ToV10,
		11: migrateV10ToV11,
		12: migratedV11ToV12,
		13: migratedV12ToV13,
		14: migratedV13ToV14,
		15: migratedV14ToV15,
		16: migratedV15ToV16
	};
	await runSchemaMigrations(log, "view-syncer", cvrSchema(shard), db, setupMigration, schemaVersionMigrationMap);
}
//#endregion
export { initViewSyncerSchema };

//# sourceMappingURL=init.js.map