// SQLite backend for the async DB adapter (dev + tests; also the current prod engine until pg cutover).
//
// Wraps the synchronous node:sqlite instance (schema applied at load in ../db.js) in the async interface
// the repos call. Results are returned via resolved Promises, so the SAME repo code runs unchanged on this
// synchronous engine and on asynchronous Postgres — the app never sees the difference.
const raw = require('../db'); // DatabaseSync instance with the full schema already applied

// node:sqlite re-prepares cheaply, but caching by SQL text avoids re-parsing on hot paths.
const cache = new Map();
function stmt(sql) {
  let s = cache.get(sql);
  if (!s) { s = raw.prepare(sql); cache.set(sql, s); }
  return s;
}
const num = (v) => (typeof v === 'bigint' ? Number(v) : v);
const runResult = (r) => ({ changes: num(r.changes), lastInsertRowid: num(r.lastInsertRowid) });

function prepare(sql) {
  return {
    get: (...p) => Promise.resolve(stmt(sql).get(...p)),
    all: (...p) => Promise.resolve(stmt(sql).all(...p)),
    run: (...p) => Promise.resolve(runResult(stmt(sql).run(...p))),
  };
}

function exec(sql) { raw.exec(sql); return Promise.resolve(); }

// Transaction primitive. SQLite is single-connection, so BEGIN/COMMIT/ROLLBACK on `raw` is safe; the
// callback gets a runner with the same async run/get shape. (The pg backend implements this on ONE pooled
// client — the reason repos must use tx() rather than bare exec('BEGIN') for multi-statement atomicity.)
async function tx(fn) {
  raw.exec('BEGIN');
  try {
    const t = {
      run: (sql, ...p) => Promise.resolve(runResult(stmt(sql).run(...p))),
      get: (sql, ...p) => Promise.resolve(stmt(sql).get(...p)),
      all: (sql, ...p) => Promise.resolve(stmt(sql).all(...p)),
    };
    const out = await fn(t);
    raw.exec('COMMIT');
    return out;
  } catch (e) {
    try { raw.exec('ROLLBACK'); } catch (_) {}
    throw e;
  }
}

function init() { return Promise.resolve(); } // schema already applied synchronously in ../db.js

module.exports = { prepare, exec, tx, init, name: 'sqlite', _raw: raw };
