import { mkdirSync } from "node:fs";
import { DatabaseSync } from "node:sqlite";
import path from "node:path";
import { isRecord } from "./rowMappers.js";
/**
 * Owns the single {@link DatabaseSync} handle for a local store and exposes
 * the low-level primitives the repositories build on: statement preparation,
 * raw exec, lifecycle close, and the schema-introspection helpers used by
 * migrations and status reporting.
 *
 * There is exactly one connection per store; WAL and foreign-keys pragmas are
 * applied once, by the migrator, against this handle.
 */
export class SqliteConnection {
    #db;
    constructor(db) {
        this.#db = db;
    }
    static open(dbPath) {
        if (dbPath !== ":memory:") {
            mkdirSync(path.dirname(dbPath), { recursive: true, mode: 0o700 });
        }
        return new SqliteConnection(new DatabaseSync(dbPath));
    }
    prepare(sql) {
        return this.#db.prepare(sql);
    }
    exec(sql) {
        this.#db.exec(sql);
    }
    close() {
        this.#db.close();
    }
    addColumnIfMissing(table, column, definition) {
        const columns = this.#db.prepare(`PRAGMA table_info(${table})`).all();
        const exists = columns.some((row) => isRecord(row) && row.name === column);
        if (!exists) {
            this.#db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
        }
    }
    schemaVersion() {
        const row = this.#db
            .prepare("SELECT COALESCE(MAX(version), 0) AS version FROM schema_migrations")
            .get();
        if (!isRecord(row) || typeof row.version !== "number")
            return 0;
        return row.version;
    }
    count(table, where) {
        const row = this.#db
            .prepare(`SELECT COUNT(*) AS count FROM ${table}${where ? ` WHERE ${where}` : ""}`)
            .get();
        if (!isRecord(row) || typeof row.count !== "number")
            return 0;
        return row.count;
    }
}
