import { afterAll, beforeAll, beforeEach, bench, describe } from "vitest";
import { openLix } from "../lix/open-lix.js";
import { sql } from "kysely";
import { uuidV7 } from "../engine/functions/uuid-v7.js";
import { getTimestamp } from "../engine/functions/timestamp.js";
const ROW_NUM = 1000;
const BATCH_SIZE = 1000;
async function createChangeBenchCtx() {
    const lix = await openLix({});
    return {
        lix,
        db: lix.db,
    };
}
async function clearChangeTables(ctx) {
    await ctx.db.deleteFrom("lix_internal_change").execute();
    await ctx.db.deleteFrom("lix_internal_snapshot").execute();
}
describe(`insert ${ROW_NUM} changes with snapshots`, () => {
    let ctx;
    beforeAll(async () => {
        ctx = await createChangeBenchCtx();
    });
    afterAll(async () => {
        await ctx.lix.close();
    });
    beforeEach(async () => {
        await clearChangeTables(ctx);
    });
    bench(`insert ${ROW_NUM} changes with snapshots`, async () => {
        const time = await getTimestamp({ lix: ctx.lix });
        for (let batch = 0; batch < ROW_NUM; batch += BATCH_SIZE) {
            const batchSize = Math.min(BATCH_SIZE, ROW_NUM - batch);
            const snapshots = [];
            const changes = [];
            for (let i = batch; i < batch + batchSize; i++) {
                const snapshotId = await uuidV7({ lix: ctx.lix });
                const snapshotContent = {
                    entity_id: `entity-${i}`,
                    schema_key: "test_entity",
                    file_id: "test_file",
                    data: {
                        value: `test-value-${i}`,
                        index: i,
                        nested: {
                            field1: `field1-${i}`,
                            field2: i * 2,
                            field3: i % 2 === 0,
                        },
                    },
                };
                snapshots.push({
                    id: snapshotId,
                    content: sql `jsonb(${JSON.stringify(snapshotContent)})`,
                });
                changes.push({
                    id: await uuidV7({ lix: ctx.lix }),
                    entity_id: `entity-${i}`,
                    schema_key: "test_entity",
                    schema_version: "1.0",
                    file_id: "test_file",
                    plugin_key: "test_plugin",
                    snapshot_id: snapshotId,
                    created_at: time,
                });
            }
            await ctx.db
                .insertInto("lix_internal_snapshot")
                .values(snapshots)
                .execute();
            await ctx.db
                .insertInto("lix_internal_change")
                .values(changes)
                .execute();
        }
    });
});
describe(`select ${ROW_NUM} changes from change view (with snapshot join)`, () => {
    let ctx;
    beforeAll(async () => {
        ctx = await createChangeBenchCtx();
        await clearChangeTables(ctx);
        const time = await getTimestamp({ lix: ctx.lix });
        for (let batch = 0; batch < ROW_NUM; batch += BATCH_SIZE) {
            const batchSize = Math.min(BATCH_SIZE, ROW_NUM - batch);
            const snapshots = [];
            const changes = [];
            for (let i = batch; i < batch + batchSize; i++) {
                const snapshotId = await uuidV7({ lix: ctx.lix });
                const snapshotContent = {
                    entity_id: `entity-${i}`,
                    schema_key: "test_entity",
                    file_id: "test_file",
                    data: {
                        value: `test-value-${i}`,
                        index: i,
                        nested: {
                            field1: `field1-${i}`,
                            field2: i * 2,
                            field3: i % 2 === 0,
                        },
                    },
                };
                snapshots.push({
                    id: snapshotId,
                    content: sql `jsonb(${JSON.stringify(snapshotContent)})`,
                });
                changes.push({
                    id: await uuidV7({ lix: ctx.lix }),
                    entity_id: `entity-${i}`,
                    schema_key: "test_entity",
                    schema_version: "1.0",
                    file_id: "test_file",
                    plugin_key: "test_plugin",
                    snapshot_id: snapshotId,
                    created_at: time,
                });
            }
            await ctx.db
                .insertInto("lix_internal_snapshot")
                .values(snapshots)
                .execute();
            await ctx.db
                .insertInto("lix_internal_change")
                .values(changes)
                .execute();
        }
    });
    afterAll(async () => {
        await ctx.lix.close();
    });
    bench(`select ${ROW_NUM} changes from change view (with snapshot join)`, async () => {
        await ctx.lix.db.selectFrom("change").selectAll().execute();
    });
});
describe(`select single change by id from change view`, () => {
    let ctx;
    let changeId;
    beforeAll(async () => {
        ctx = await createChangeBenchCtx();
        await clearChangeTables(ctx);
        const time = await getTimestamp({ lix: ctx.lix });
        const snapshotId = await uuidV7({ lix: ctx.lix });
        changeId = await uuidV7({ lix: ctx.lix });
        await ctx.db
            .insertInto("lix_internal_snapshot")
            .values({
            id: snapshotId,
            content: sql `jsonb(${JSON.stringify({
                entity_id: "single-entity",
                data: { value: "test" },
            })})`,
        })
            .execute();
        await ctx.db
            .insertInto("lix_internal_change")
            .values({
            id: changeId,
            entity_id: "single-entity",
            schema_key: "test_entity",
            schema_version: "1.0",
            file_id: "test_file",
            plugin_key: "test_plugin",
            snapshot_id: snapshotId,
            created_at: time,
        })
            .execute();
    });
    afterAll(async () => {
        await ctx.lix.close();
    });
    bench(`select single change by id from change view`, async () => {
        await ctx.lix.db
            .selectFrom("change")
            .where("id", "=", changeId)
            .selectAll()
            .execute();
    });
});
describe(`select changes with filtering by schema_key`, () => {
    let ctx;
    beforeAll(async () => {
        ctx = await createChangeBenchCtx();
        await clearChangeTables(ctx);
        const time = await getTimestamp({ lix: ctx.lix });
        for (let batch = 0; batch < ROW_NUM; batch += BATCH_SIZE) {
            const batchSize = Math.min(BATCH_SIZE, ROW_NUM - batch);
            const snapshots = [];
            const changes = [];
            for (let i = batch; i < batch + batchSize; i++) {
                const snapshotId = await uuidV7({ lix: ctx.lix });
                const schemaKey = i % 3 === 0
                    ? "test_entity_a"
                    : i % 3 === 1
                        ? "test_entity_b"
                        : "test_entity_c";
                snapshots.push({
                    id: snapshotId,
                    content: sql `jsonb(${JSON.stringify({
                        entity_id: `entity-${i}`,
                        data: { value: `test-${i}` },
                    })})`,
                });
                changes.push({
                    id: await uuidV7({ lix: ctx.lix }),
                    entity_id: `entity-${i}`,
                    schema_key: schemaKey,
                    schema_version: "1.0",
                    file_id: "test_file",
                    plugin_key: "test_plugin",
                    snapshot_id: snapshotId,
                    created_at: time,
                });
            }
            await ctx.db
                .insertInto("lix_internal_snapshot")
                .values(snapshots)
                .execute();
            await ctx.db
                .insertInto("lix_internal_change")
                .values(changes)
                .execute();
        }
    });
    afterAll(async () => {
        await ctx.lix.close();
    });
    bench(`select changes with filtering by schema_key`, async () => {
        await ctx.lix.db
            .selectFrom("change")
            .where("schema_key", "=", "test_entity_a")
            .selectAll()
            .execute();
    });
});
describe(`compare: direct query vs change view`, () => {
    let ctx;
    let changeId;
    beforeAll(async () => {
        ctx = await createChangeBenchCtx();
        await clearChangeTables(ctx);
        const time = await getTimestamp({ lix: ctx.lix });
        const snapshotId = await uuidV7({ lix: ctx.lix });
        changeId = await uuidV7({ lix: ctx.lix });
        await ctx.db
            .insertInto("lix_internal_snapshot")
            .values({
            id: snapshotId,
            content: sql `jsonb(${JSON.stringify({
                entity_id: "test-entity",
                data: { value: "test" },
            })})`,
        })
            .execute();
        await ctx.db
            .insertInto("lix_internal_change")
            .values({
            id: changeId,
            entity_id: "test-entity",
            schema_key: "test_entity",
            schema_version: "1.0",
            file_id: "test_file",
            plugin_key: "test_plugin",
            snapshot_id: snapshotId,
            created_at: time,
        })
            .execute();
    });
    afterAll(async () => {
        await ctx.lix.close();
    });
    bench(`compare: direct query vs change view`, async () => {
        await ctx.db
            .selectFrom("lix_internal_change as c")
            .innerJoin("lix_internal_snapshot as s", "s.id", "c.snapshot_id")
            .select([
            "c.id",
            "c.entity_id",
            "c.schema_key",
            "c.schema_version",
            "c.file_id",
            "c.plugin_key",
            "c.created_at",
            sql `json(s.content)`.as("snapshot_content"),
        ])
            .where("c.id", "=", changeId)
            .execute();
        await ctx.lix.db
            .selectFrom("change")
            .where("id", "=", changeId)
            .selectAll()
            .execute();
    });
});
describe(`select changes with NULL snapshots (deletions)`, () => {
    let ctx;
    beforeAll(async () => {
        ctx = await createChangeBenchCtx();
        await clearChangeTables(ctx);
        const time = await getTimestamp({ lix: ctx.lix });
        const totalDeletions = Math.floor(ROW_NUM / 10);
        for (let batch = 0; batch < totalDeletions; batch += BATCH_SIZE) {
            const batchSize = Math.min(BATCH_SIZE, totalDeletions - batch);
            const changes = [];
            for (let i = batch; i < batch + batchSize; i++) {
                changes.push({
                    id: await uuidV7({ lix: ctx.lix }),
                    entity_id: `deleted-entity-${i}`,
                    schema_key: "test_entity",
                    schema_version: "1.0",
                    file_id: "test_file",
                    plugin_key: "test_plugin",
                    snapshot_id: "no-content",
                    created_at: time,
                });
            }
            await ctx.db
                .insertInto("lix_internal_change")
                .values(changes)
                .execute();
        }
    });
    afterAll(async () => {
        await ctx.lix.close();
    });
    bench(`select changes with NULL snapshots (deletions)`, async () => {
        await ctx.lix.db
            .selectFrom("change")
            .where("snapshot_content", "is", null)
            .selectAll()
            .execute();
    });
});
//# sourceMappingURL=schema.bench.js.map