/**
 * @cc-platform/server/db — SQLite database factory
 *
 * Extracted from the common setup patterns in both
 * remoteturtle/server/database.js and Inventory-Manager-CC/web/server/db.js.
 *
 * Provides:
 *   - Database creation with WAL mode and production-ready pragmas
 *   - Directory validation and creation
 *   - Schema initialization
 *   - Debounced save support (batch writes on intervals)
 *   - Clean shutdown with flush
 *
 * Usage:
 *   const { createDatabase } = require('@cc-platform/server/db');
 *   const { db, debouncedSave, close } = createDatabase('/data/myservice.db', {
 *     schema: `CREATE TABLE IF NOT EXISTS items (...)`,
 *     debounceMs: 2000,
 *   });
 *
 *   // Use db directly for queries
 *   const row = db.prepare('SELECT * FROM items WHERE id = ?').get(1);
 *
 *   // Use debouncedSave to batch expensive saves
 *   debouncedSave(() => { ... bulk insert ... });
 *
 *   // On shutdown
 *   close();
 */

'use strict';

const Database = require('better-sqlite3');
const path = require('path');
const fs = require('fs');

/**
 * @typedef {Object} DatabaseOptions
 * @property {string}  [schema]       SQL to execute on init (CREATE TABLE IF NOT EXISTS ...)
 * @property {number}  [debounceMs]   Debounce interval for batched saves (default: 2000)
 * @property {number}  [cacheSize]    SQLite cache size pragma (default: -8000 = ~8MB)
 * @property {string}  [tempStore]    SQLite temp_store pragma (default: 'MEMORY')
 * @property {boolean} [foreignKeys]  Enable foreign keys (default: true)
 */

/**
 * Create and initialize a SQLite database with production-ready defaults.
 *
 * @param {string} dbPath - Path to the database file
 * @param {DatabaseOptions} opts - Configuration options
 * @returns {{ db, debouncedSave, flushPendingSave, close }}
 */
function createDatabase(dbPath, opts = {}) {
  // Ensure directory exists and is writable
  const dir = path.dirname(path.resolve(dbPath));
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }

  // Verify directory is writable
  try {
    fs.accessSync(dir, fs.constants.W_OK);
  } catch (e) {
    throw new Error(`Database directory is not writable: ${dir}`);
  }

  const db = new Database(dbPath);

  // Production-ready pragmas
  db.pragma('journal_mode = WAL');
  db.pragma('synchronous = NORMAL');

  if (opts.foreignKeys !== false) {
    db.pragma('foreign_keys = ON');
  }
  if (opts.cacheSize) {
    db.pragma(`cache_size = ${opts.cacheSize}`);
  }
  if (opts.tempStore) {
    db.pragma(`temp_store = ${opts.tempStore}`);
  }

  // Schema initialization
  if (opts.schema) {
    db.exec(opts.schema);
  }

  // --- Debounced save support ---
  const debounceMs = opts.debounceMs || 2000;
  let saveTimer = null;
  let pendingSave = null;

  /**
   * Schedule a save function to run after the debounce interval.
   * If called again before the timer fires, the latest save function replaces
   * the previous one (only the most recent save runs).
   *
   * @param {Function} saveFn - The save operation to execute
   */
  function debouncedSave(saveFn) {
    pendingSave = saveFn;
    if (!saveTimer) {
      saveTimer = setTimeout(() => {
        saveTimer = null;
        if (pendingSave) {
          try {
            pendingSave();
          } catch (e) {
            console.error('[db] Debounced save error:', e.message);
          }
          pendingSave = null;
        }
      }, debounceMs);
    }
  }

  /**
   * Immediately execute any pending save and clear the timer.
   * Call this during shutdown to avoid data loss.
   */
  function flushPendingSave() {
    if (saveTimer) {
      clearTimeout(saveTimer);
      saveTimer = null;
    }
    if (pendingSave) {
      try {
        pendingSave();
      } catch (e) {
        console.error('[db] Flush save error:', e.message);
      }
      pendingSave = null;
    }
  }

  /**
   * Flush pending saves and close the database connection.
   * Safe to call multiple times.
   */
  function close() {
    flushPendingSave();
    try {
      db.close();
    } catch (e) {
      // Already closed — ignore
    }
  }

  return { db, debouncedSave, flushPendingSave, close };
}

module.exports = { createDatabase };
