'use strict';
const chokidar = require('chokidar');
const path = require('path');
const { fullScan, processResultDir } = require('./scanner');
const { resetByFileIdAndDevice } = require('./db');
const { broadcast } = require('./sse');

let targetWatcher  = null;
let resultsWatcher = null;

function debounce(fn, ms) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), ms);
  };
}

function startWatching(targetDir, resultsDir) {
  stopWatching();
  if (!targetDir || !resultsDir) return;

  // ── Target dir ────────────────────────────────────────────────────────────
  // Any change to test files (new cases added or removed) triggers a full
  // rescan so the test list stays in sync.
  targetWatcher = chokidar.watch(targetDir, {
    depth: 1,
    ignoreInitial: true,
    awaitWriteFinish: { stabilityThreshold: 500, pollInterval: 100 },
  });

  const debouncedFullScan = debounce(async () => {
    await fullScan(targetDir, resultsDir);
    broadcast({ type: 'update' });
  }, 1000);

  targetWatcher.on('add',    debouncedFullScan);
  targetWatcher.on('unlink', debouncedFullScan);

  // ── Results dir ───────────────────────────────────────────────────────────
  // depth: 1 covers both immediate result subdirectories (addDir/unlinkDir)
  // and log files inside them (add).
  resultsWatcher = chokidar.watch(resultsDir, {
    depth: 1,
    ignoreInitial: true,
    awaitWriteFinish: { stabilityThreshold: 2000, pollInterval: 200 },
  });

  // New result directory → mark test complete
  resultsWatcher.on('addDir', async (dirPath) => {
    if (path.normalize(dirPath) === path.normalize(resultsDir)) return;
    const dirName = path.basename(dirPath);
    await processResultDir(resultsDir, dirName);
    broadcast({ type: 'update' });
  });

  // New log file inside a result directory → update timing
  resultsWatcher.on('add', async (filePath) => {
    const dirPath = path.dirname(filePath);
    if (path.normalize(dirPath) === path.normalize(resultsDir)) return;
    const dirName = path.basename(dirPath);
    await processResultDir(resultsDir, dirName);
    broadcast({ type: 'update' });
  });

  // Result directory deleted → reset test to pending
  resultsWatcher.on('unlinkDir', (dirPath) => {
    if (path.normalize(dirPath) === path.normalize(resultsDir)) return;
    const dirName = path.basename(dirPath);
    const segs   = dirName.split(/[_\-]/);
    const test_id = segs.find(s => /^R\d+[A-Z0-9]+$/i.test(s)) || null;
    const device  = segs.find(s => /^CGW\d+$/i.test(s))        || null;
    if (test_id) {
      resetByFileIdAndDevice(test_id, device);
      broadcast({ type: 'update' });
    }
  });
}

function stopWatching() {
  if (targetWatcher)  { targetWatcher.close();  targetWatcher  = null; }
  if (resultsWatcher) { resultsWatcher.close(); resultsWatcher = null; }
}

module.exports = { startWatching, stopWatching };
