'use strict';
// Deferred, one-shot brain-DB space optimization for users upgrading from a pre-int8 build.
// Runs OFF the boot path (registered with a multi-minute startDelay) so it never adds to the
// boot storm, and self-gates to run at most once via a kv flag.
//
// Safety model:
//   - SIZE-GATED: the int8 rebuild + FTS rebuild + VACUUM block the (single) event loop for
//     their duration. Tiny for a few-thousand-vector store, ~tens of seconds for hundreds of
//     thousands. So only auto-run when the embedding store is small; otherwise log a one-time
//     notice pointing at the supervised CLI (`scripts/db-optimize/migrate.js`, run with Wall-E
//     stopped) and never nag again.
//   - NEVER drops lost_and_found automatically: that is a per-install SQLite .recover artifact
//     and dropping a recovery table needs explicit human confirmation.
//   - Idempotent + crash-safe: each phase checks if already applied and is transactional, so a
//     restart mid-run simply retries; float32 vectors are never lost (rolled back on crash).

const brain = require('../brain');

const KV_STATE = 'brain:optimize:v1';            // unset | 'done' | 'notified'
const AUTO_MAX = parseInt(process.env.BRAIN_OPTIMIZE_AUTO_MAX || '20000', 10);

async function runOnce() {
  const state = brain.getKv(KV_STATE);
  if (state === 'done' || state === 'notified') return { done: true, _done: true, skipped: state };

  let db;
  try { db = brain.getDb(); } catch { return { done: false, reason: 'no-db' }; }

  // sqlite-vec must be loaded on this connection for the int8 quantization functions.
  try { require('../embeddings').ensureVecLoaded(); } catch {}

  let mig;
  try { mig = require('../scripts/db-optimize/migrate'); } catch (e) {
    console.error('[brain-optimize] migration module unavailable:', e.message);
    brain.setKv(KV_STATE, 'notified');
    return { done: true, _done: true, skipped: 'module-missing' };
  }

  if (!mig.needsOptimization(db)) {
    brain.setKv(KV_STATE, 'done');
    return { done: true, _done: true, alreadyOptimal: true };
  }

  const n = mig.embeddingCount(db);
  if (n > AUTO_MAX) {
    console.warn(
      `[brain-optimize] Brain has ${n} float32 embeddings (> ${AUTO_MAX} auto cap). ` +
      `To reclaim disk, stop Wall-E and run: node wall-e/scripts/db-optimize/migrate.js "${brain.getDbPath()}". ` +
      `Set BRAIN_OPTIMIZE_AUTO_MAX higher to auto-migrate anyway (briefly blocks the event loop).`
    );
    brain.setKv(KV_STATE, 'notified');
    return { done: true, _done: true, skipped: 'large', embeddingCount: n };
  }

  const t0 = Date.now();
  mig.optimizeBrain(db, {
    vacuum: true,
    dropLostAndFound: false, // recovery artifact — never auto-drop
    log: (...a) => console.log('[brain-optimize]', ...a),
  });
  brain.setKv(KV_STATE, 'done');
  const ms = Date.now() - t0;
  console.log(`[brain-optimize] upgrade migration complete in ${(ms / 1000).toFixed(1)}s (${n} vectors → int8)`);
  return { done: true, _done: true, migrated: true, embeddingCount: n, ms };
}

module.exports = { runOnce, KV_STATE, AUTO_MAX };
