import { internalQueryBuilder } from "../engine/internal-query-builder.js";
/**
 * Create a synchronous query builder factory bound to an engine.
 *
 * Returns a `querySync(table)` function that mirrors Kysely's
 * `selectFrom(table)` builder, but with synchronous execution via
 * `.execute()`, `.executeTakeFirst()`, and `.executeTakeFirstOrThrow()`.
 *
 * When to use
 * - Inside plugins: pass the returned `querySync` into `detectChanges()` so
 *   plugins can read current state synchronously while computing changes.
 * - In unit tests: construct `querySync` from an in‑process Lix (e.g.
 *   `InMemoryEnvironment`) using `createQuerySync({ engine: lix.engine! })`
 *   and call your plugin's `detectChanges({ querySync, ... })` directly.
 *
 * Engine availability
 * - In in‑process environments (like the default in‑memory environment),
 *   `lix.engine` is available and can be passed here.
 * - In worker/remote environments, `lix.engine` is undefined on the host
 *   thread. In those cases, use integration tests that drive the file
 *   handlers or a test environment that exposes the engine.
 *
 * JSON behavior
 * - `snapshot_content` is parsed to objects to match normal Kysely queries.
 *   Other JSON columns are returned as raw JSON strings; parse if needed.
 *
 * @example
 * // Unit testing a plugin's detectChanges directly
 * import { openLix, createQuerySync } from '@lix-js/sdk'
 * import { detectChanges } from '../src/detect-changes.js'
 *
 * const lix = await openLix({})
 * const querySync = createQuerySync({ engine: lix.engine! })
 *
 * const after = {
 *   id: 'file1',
 *   path: '/doc.md',
 *   data: new TextEncoder().encode('# Hello'),
 *   metadata: {}
 * }
 *
 * const changes = detectChanges({ querySync, after })
 * expect(Array.isArray(changes)).toBe(true)
 */
export function createQuerySync(args) {
    /**
     * Starts a SELECT from the given table and returns a Kysely builder
     * whose `.execute()` runs synchronously.
     */
    function querySync(table) {
        const base = internalQueryBuilder.selectFrom(table);
        return wrapBuilder(base, args.engine);
    }
    return querySync;
}
function wrapBuilder(builder, engine) {
    return new Proxy(builder, {
        get(target, prop, _receiver) {
            if (prop === "execute") {
                return () => parseSnapshotRows(engine.executeSync(target.compile()).rows);
            }
            if (prop === "executeTakeFirst") {
                return () => {
                    const rows = parseSnapshotRows(engine.executeSync(target.compile()).rows);
                    return rows[0] ?? undefined;
                };
            }
            if (prop === "executeTakeFirstOrThrow") {
                return () => {
                    const rows = parseSnapshotRows(engine.executeSync(target.compile()).rows);
                    if (!rows[0])
                        throw new Error("No result");
                    return rows[0];
                };
            }
            const value = target[prop];
            if (typeof value === "function") {
                return (...args) => {
                    const res = value.apply(target, args);
                    // If the method returns another builder (typical in Kysely),
                    // wrap it again to keep `.execute()` synchronous.
                    if (res &&
                        typeof res === "object" &&
                        typeof res.compile === "function") {
                        return wrapBuilder(res, engine);
                    }
                    return res;
                };
            }
            return value;
        },
    });
}
function parseSnapshotRows(rows) {
    return rows.map((r) => {
        if (r && typeof r === "object" && "snapshot_content" in r) {
            const v = r.snapshot_content;
            if (typeof v === "string") {
                try {
                    return { ...r, snapshot_content: JSON.parse(v) };
                }
                catch {
                    // fall through if not valid JSON
                }
            }
        }
        return r;
    });
}
//# sourceMappingURL=query-sync.js.map