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

const DB_PATH     = path.join(__dirname, 'dashboard.db');
const CONFIG_JSON = path.join(__dirname, 'config.json');

const db = new Database(DB_PATH);

// Enable WAL for better concurrent read performance
db.pragma('journal_mode = WAL');

// ── Schema ───────────────────────────────────────────────────────────────────
db.exec(`
  CREATE TABLE IF NOT EXISTS config (
    key   TEXT PRIMARY KEY,
    value TEXT NOT NULL
  );

  CREATE TABLE IF NOT EXISTS tests (
    id               TEXT PRIMARY KEY,
    test_id          TEXT,
    parent_dir       TEXT,
    filename         TEXT,
    interference     TEXT,
    device           TEXT,
    rotation         TEXT,
    test_point       TEXT,
    station          TEXT,
    band             TEXT,
    channel          TEXT,
    bandwidth        TEXT,
    rssi             TEXT,
    direction        TEXT,
    completed        INTEGER NOT NULL DEFAULT 0,
    completed_at     TEXT,
    duration_seconds REAL
  );

  CREATE INDEX IF NOT EXISTS idx_tests_test_id ON tests (test_id);
  CREATE INDEX IF NOT EXISTS idx_tests_device  ON tests (device);
`);

// Add new columns to existing databases (idempotent)
for (const colDef of ['tput_mbps REAL', 'dl_rssi_dbm REAL', 'ul_rssi_dbm REAL', 'tput_results TEXT']) {
  try { db.exec(`ALTER TABLE tests ADD COLUMN ${colDef}`); } catch { /* already exists */ }
}

// ── One-time migration from config.json ──────────────────────────────────────
{
  const alreadyMigrated = db.prepare("SELECT COUNT(*) AS n FROM config").get().n > 0;
  if (!alreadyMigrated && fs.existsSync(CONFIG_JSON)) {
    try {
      const legacy = JSON.parse(fs.readFileSync(CONFIG_JSON, 'utf8'));
      const insert = db.prepare('INSERT OR IGNORE INTO config (key, value) VALUES (?, ?)');
      const migrate = db.transaction((obj) => {
        for (const [k, v] of Object.entries(obj)) {
          if (v != null) insert.run(k, String(v));
        }
      });
      migrate(legacy);
      console.log('[db] Migrated config.json → SQLite');
    } catch (e) {
      console.warn('[db] Could not migrate config.json:', e.message);
    }
  }
}

// ── Config ───────────────────────────────────────────────────────────────────
const _stmtGetConfig = db.prepare('SELECT value FROM config WHERE key = ?');
const _stmtSetConfig = db.prepare('INSERT OR REPLACE INTO config (key, value) VALUES (?, ?)');
const _stmtDelConfig = db.prepare('DELETE FROM config WHERE key = ?');

function getConfig(key)        { return _stmtGetConfig.get(key)?.value ?? null; }
function setConfig(key, value) { _stmtSetConfig.run(key, value); }
function delConfig(key)        { _stmtDelConfig.run(key); }

// ── Tests ─────────────────────────────────────────────────────────────────────
const _stmtUpsertTest = db.prepare(`
  INSERT INTO tests
    (id, test_id, parent_dir, filename, interference, device, rotation,
     test_point, station, band, channel, bandwidth, rssi, direction)
  VALUES
    (@id, @test_id, @parent_dir, @filename, @interference, @device, @rotation,
     @test_point, @station, @band, @channel, @bandwidth, @rssi, @direction)
  ON CONFLICT(id) DO UPDATE SET
    test_id      = excluded.test_id,
    parent_dir   = excluded.parent_dir,
    filename     = excluded.filename,
    interference = excluded.interference,
    device       = excluded.device,
    rotation     = excluded.rotation,
    test_point   = excluded.test_point,
    station      = excluded.station,
    band         = excluded.band,
    channel      = excluded.channel,
    bandwidth    = excluded.bandwidth,
    rssi         = excluded.rssi,
    direction    = excluded.direction
    -- completed / completed_at / duration_seconds intentionally preserved
`);

const _stmtMarkCompleted = db.prepare(`
  UPDATE tests
  SET completed = 1, completed_at = ?, duration_seconds = ?, tput_results = ?
  WHERE test_id = ? AND (? IS NULL OR device = ?)
`);

const _stmtResetTest = db.prepare(`
  UPDATE tests
  SET completed = 0, completed_at = NULL, duration_seconds = NULL, tput_results = NULL
  WHERE test_id = ? AND (? IS NULL OR device = ?)
`);

const _stmtGetStation = db.prepare('SELECT station FROM tests WHERE test_id = ? AND device = ? LIMIT 1');

const _stmtClearTests  = db.prepare('DELETE FROM tests');
const _stmtGetAllTests = db.prepare('SELECT * FROM tests');
const _stmtCountTests  = db.prepare('SELECT COUNT(*) AS n FROM tests');

function upsertTest(test) {
  _stmtUpsertTest.run(test);
}

function markCompleted(test_id, device, completed_at, duration_seconds, tputResults = null) {
  const json = tputResults && tputResults.length > 0 ? JSON.stringify(tputResults) : null;
  _stmtMarkCompleted.run(completed_at, duration_seconds, json, test_id, device, device);
}

function getStationForTest(test_id, device) {
  return _stmtGetStation.get(test_id, device)?.station ?? null;
}

function resetByFileIdAndDevice(test_id, device) {
  _stmtResetTest.run(test_id, device, device);
}

function clearTests() { _stmtClearTests.run(); }
function getAllTests() { return _stmtGetAllTests.all(); }
function countTests() { return _stmtCountTests.get().n; }

module.exports = {
  getConfig, setConfig, delConfig,
  upsertTest, markCompleted, resetByFileIdAndDevice, clearTests, getAllTests, countTests,
  getStationForTest,
};
