import { and, eq, getTableColumns, inArray } from "drizzle-orm";
import { assertNever } from "../util/assert-never.js";
import * as schema from "./schema.js";
const { scope: _, ...columns } = getTableColumns(schema.resources);
/**
 * Represents the SQL operations for a SQLite-backed state store.
 * DOES NOT include serialization/deserialization — that is handled by the `StateStoreProxy` class.
 */
export class SQLiteStateStoreOperations {
    db;
    context;
    constructor(db, context) {
        this.db = db;
        this.context = context;
    }
    async dispatch(method, params) {
        switch (method) {
            case "init":
                return;
            case "deinit":
                return;
            case "list":
                return this.list();
            case "listScopes":
                return this.listScopes();
            case "count":
                return this.count();
            case "get": {
                const [key] = params;
                return this.get(key);
            }
            case "getBatch": {
                const [keys] = params;
                return this.getBatch(keys);
            }
            case "all":
                return this.all();
            case "set": {
                const [key, state] = params;
                return this.set(key, state);
            }
            case "delete": {
                const [key] = params;
                return this.delete(key);
            }
            default:
                assertNever(method);
        }
    }
    async list() {
        const result = await this.db
            .select({ id: schema.resources.id })
            .from(schema.resources)
            .where(eq(schema.resources.scope, this.context.chain));
        return result.map((r) => r.id);
    }
    async listScopes() {
        const rows = await this.db
            .selectDistinct({ scope: schema.resources.scope })
            .from(schema.resources);
        const prefix = this.context.chain;
        const names = new Set();
        for (const row of rows) {
            const scope = row.scope;
            if (scope.length !== prefix.length + 1)
                continue;
            let matches = true;
            for (let i = 0; i < prefix.length; i++) {
                if (scope[i] !== prefix[i]) {
                    matches = false;
                    break;
                }
            }
            if (matches)
                names.add(scope[prefix.length]);
        }
        return [...names];
    }
    async count() {
        const result = await this.db.$count(this.db
            .select()
            .from(schema.resources)
            .where(eq(schema.resources.scope, this.context.chain)));
        return result;
    }
    async get(key) {
        const [result] = await this.db
            .select(columns)
            .from(schema.resources)
            .where(and(eq(schema.resources.scope, this.context.chain), eq(schema.resources.id, key)));
        if (!result) {
            return undefined;
        }
        return {
            ...result,
            props: result.props ?? undefined,
            oldProps: result.oldProps ?? undefined,
        };
    }
    async all() {
        const result = await this.db
            .select(columns)
            .from(schema.resources)
            .where(eq(schema.resources.scope, this.context.chain));
        const record = {};
        for (const r of result) {
            record[r.id] = {
                ...r,
                props: r.props ?? undefined,
                oldProps: r.oldProps ?? undefined,
            };
        }
        return record;
    }
    async set(_key, state) {
        await this.db
            .insert(schema.resources)
            .values({
            ...state,
            scope: this.context.chain,
        })
            .onConflictDoUpdate({
            target: [schema.resources.id, schema.resources.scope],
            set: {
                ...state,
            },
        });
    }
    async delete(key) {
        await this.db
            .delete(schema.resources)
            .where(and(eq(schema.resources.scope, this.context.chain), eq(schema.resources.id, key)));
    }
    async getBatch(keys) {
        const result = await this.db
            .select(columns)
            .from(schema.resources)
            .where(and(eq(schema.resources.scope, this.context.chain), inArray(schema.resources.id, keys)));
        const record = {};
        for (const r of result) {
            record[r.id] = {
                ...r,
                props: r.props ?? undefined,
                oldProps: r.oldProps ?? undefined,
            };
        }
        return record;
    }
}
//# sourceMappingURL=operations.js.map