import { populateFromExistingTables } from "../../replicator/schema/column-metadata.js";
import { CREATE_RUNTIME_EVENTS_TABLE, recordEvent } from "../../replicator/schema/replication-state.js";
import { listTables } from "../../../db/lite-tables.js";
import { runSchemaMigrations } from "../../../db/migration-lite.js";
import { AutoResetSignal } from "../../change-streamer/schema/tables.js";
import { SqliteError } from "@rocicorp/zero-sqlite3";
//#region ../zero-cache/src/services/change-source/common/replica-schema.ts
async function initReplica(log, debugName, dbPath, initialSync) {
	const setupMigration = {
		migrateSchema: (log, tx) => initialSync(log, tx),
		minSafeVersion: 1
	};
	try {
		await runSchemaMigrations(log, debugName, dbPath, setupMigration, schemaVersionMigrationMap);
	} catch (e) {
		if (e instanceof SqliteError && e.code === "SQLITE_CORRUPT") throw new AutoResetSignal(e.message);
		throw e;
	}
}
async function upgradeReplica(log, debugName, dbPath) {
	await runSchemaMigrations(log, debugName, dbPath, { migrateSchema: () => {
		throw new Error("This should only be called for already synced replicas");
	} }, schemaVersionMigrationMap);
}
var CREATE_V6_COLUMN_METADATA_TABLE = `
  CREATE TABLE "_zero.column_metadata" (
    table_name TEXT NOT NULL,
    column_name TEXT NOT NULL,
    upstream_type TEXT NOT NULL,
    is_not_null INTEGER NOT NULL,
    is_enum INTEGER NOT NULL,
    is_array INTEGER NOT NULL,
    character_max_length INTEGER,
    PRIMARY KEY (table_name, column_name)
  );
`;
var CREATE_V7_CHANGE_LOG = `
  CREATE TABLE "_zero.changeLog2" (
    "stateVersion"              TEXT NOT NULL,
    "pos"                       INT  NOT NULL,
    "table"                     TEXT NOT NULL,
    "rowKey"                    TEXT NOT NULL,
    "op"                        TEXT NOT NULL,
    PRIMARY KEY("stateVersion", "pos"),
    UNIQUE("table", "rowKey")
  );
`;
var CREATE_V9_TABLE_METADATA_TABLE = `
  CREATE TABLE "_zero.tableMetadata" (
    "schema"    TEXT NOT NULL,
    "table"     TEXT NOT NULL,
    "metadata"  TEXT NOT NULL,
    PRIMARY KEY ("schema", "table")
  );
`;
var schemaVersionMigrationMap = {
	4: {
		migrateSchema: () => {
			throw new AutoResetSignal("upgrading replica to new schema");
		},
		minSafeVersion: 3
	},
	5: {
		migrateSchema: (_, db) => {
			db.exec(CREATE_RUNTIME_EVENTS_TABLE);
		},
		migrateData: (_, db) => {
			recordEvent(db, "upgrade");
		}
	},
	6: {},
	7: { migrateSchema: (_, db) => {
		db.exec(`DELETE FROM "_zero.changeLog"`);
		db.exec(CREATE_V7_CHANGE_LOG);
	} },
	8: {
		migrateSchema: (_, db) => {
			if (!db.prepare(`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = '_zero.column_metadata'`).get()) db.exec(CREATE_V6_COLUMN_METADATA_TABLE);
		},
		migrateData: (_, db) => {
			db.exec(`DELETE FROM "_zero.column_metadata"`);
			populateFromExistingTables(db, listTables(db, false, false));
		}
	},
	9: { migrateSchema: (_, db) => {
		db.exec(`
        ALTER TABLE "_zero.changeLog2" 
          ADD COLUMN "backfillingColumnVersions" TEXT DEFAULT '{}';
        ALTER TABLE "_zero.column_metadata"
          ADD COLUMN backfill TEXT;
      ` + CREATE_V9_TABLE_METADATA_TABLE);
	} },
	10: { migrateSchema: (_, db) => {
		db.exec(`
        ALTER TABLE "_zero.replicationConfig" 
          ADD COLUMN "initialSyncContext" TEXT DEFAULT '{}';
      `);
	} },
	11: { migrateSchema: (_, db) => {
		db.exec(`
        ALTER TABLE "_zero.tableMetadata"
          ADD COLUMN "minRowVersion" TEXT NOT NULL DEFAULT '00';

        -- Removing the NOT NULL constraint from "metadata" requires copying
        -- the column. We piggyback the rename to "upstreamMetadata" here.
        ALTER TABLE "_zero.tableMetadata"
          ADD COLUMN "upstreamMetadata" TEXT;
        UPDATE "_zero.tableMetadata" SET "upstreamMetadata" = "metadata";
        ALTER TABLE "_zero.tableMetadata" DROP "metadata";
      `);
	} },
	12: {
		migrateSchema: (_, db) => {
			db.exec(`
        ALTER TABLE "_zero.tableMetadata"
          ADD COLUMN "metadata" TEXT;
      `);
		},
		migrateData: (_, db) => {
			db.exec(`
        UPDATE "_zero.tableMetadata" 
          SET "upstreamMetadata" = COALESCE("metadata", "upstreamMetadata"),
              "metadata" = NULL;
      `);
		}
	},
	13: {
		migrateSchema: (_, db) => {
			db.exec(`
        ALTER TABLE "_zero.replicationState" ADD COLUMN writeTimeMs INTEGER;
      `);
		},
		migrateData: (_, db) => {
			db.exec(`
        UPDATE "_zero.replicationState" 
          SET writeTimeMs = COALESCE(writeTimeMs, unixepoch('subsec') * 1000)`);
		}
	}
};
Object.keys(schemaVersionMigrationMap).reduce((prev, curr) => Math.max(prev, parseInt(curr)), 0);
//#endregion
export { initReplica, upgradeReplica };

//# sourceMappingURL=replica-schema.js.map