import { watch } from 'fs';
import { join } from 'path';

let watcher = null;
const DEBOUNCE_MS = 800;
const COOLDOWN_MS = 5000;

// Per-file debounce timers and cooldown tracking
const fileTimers = new Map();
const fileCooldowns = new Map();

export function startWatching(dirPath, onChange) {
  if (watcher) stopWatching();
  if (typeof onChange !== 'function') throw new Error('onChange callback required');

  watcher = watch(dirPath, { recursive: true }, (eventType, filename) => {
    if (!filename || filename.startsWith('.') || filename.endsWith('~') || filename.endsWith('.tmp')) return;

    // Skip if this file is in cooldown (already fired recently)
    const now = Date.now();
    const lastFired = fileCooldowns.get(filename);
    if (lastFired && (now - lastFired) < COOLDOWN_MS) return;

    // Per-file debounce: reset timer for this specific file
    if (fileTimers.has(filename)) clearTimeout(fileTimers.get(filename));

    fileTimers.set(filename, setTimeout(() => {
      fileTimers.delete(filename);
      fileCooldowns.set(filename, Date.now());
      try {
        onChange(eventType, filename, join(dirPath, filename));
      } catch (err) {
        console.error(`[file-watcher] Callback error: ${err.message}`);
      }
    }, DEBOUNCE_MS));
  });

  watcher.on('error', (err) => {
    console.error(`[file-watcher] Error: ${err.message}`);
  });

  console.log(`[file-watcher] Watching: ${dirPath}`);
  return true;
}

export function stopWatching() {
  // Clear all per-file timers
  for (const timer of fileTimers.values()) clearTimeout(timer);
  fileTimers.clear();
  fileCooldowns.clear();

  if (watcher) {
    watcher.close();
    watcher = null;
    console.log('[file-watcher] Stopped watching');
  }
}

export function isWatching() {
  return watcher !== null;
}
