'use strict';
const fs = require('fs');
const path = require('path');
const EventEmitter = require('events');

const CONFIG_PATH = path.join(__dirname, '..', 'wall-e-config.json');

class ConfigWatcher extends EventEmitter {
  constructor() {
    super();
    this._watcher = null;
    this._debounceTimer = null;
    this._reattachTimer = null;
    this._lastConfig = null;
  }

  start() {
    // Load initial config
    this._lastConfig = this._readConfig();

    try {
      // Watch for changes with fs.watch (debounced 500ms)
      this._watcher = fs.watch(CONFIG_PATH, () => {
        if (this._debounceTimer) clearTimeout(this._debounceTimer);
        this._debounceTimer = setTimeout(() => this._onFileChange(), 500);
      });

      // Handle watcher errors (file deleted, renamed)
      this._watcher.on('error', () => this._reattach());
    } catch {
      // Config file may not exist yet — retry later
      this._reattachTimer = setTimeout(() => {
        this._reattachTimer = null;
        this._reattach();
      }, 5000);
    }
  }

  stop() {
    if (this._watcher) { this._watcher.close(); this._watcher = null; }
    if (this._debounceTimer) { clearTimeout(this._debounceTimer); this._debounceTimer = null; }
    if (this._reattachTimer) { clearTimeout(this._reattachTimer); this._reattachTimer = null; }
  }

  _readConfig() {
    try {
      return JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
    } catch (e) {
      console.error('[config-watcher] Failed to read config:', e.message);
      return null;
    }
  }

  _onFileChange() {
    const newConfig = this._readConfig();
    if (!newConfig) return; // Invalid JSON — keep previous

    const old = this._lastConfig;
    this._lastConfig = newConfig;

    // Emit change events for hot-reloadable sections
    // Intervals
    if (JSON.stringify(old?.intervals) !== JSON.stringify(newConfig.intervals)) {
      this.emit('intervals', newConfig.intervals);
    }
    // Adapters
    if (JSON.stringify(old?.adapters) !== JSON.stringify(newConfig.adapters)) {
      this.emit('adapters', newConfig.adapters);
    }
    // Coding config
    if (JSON.stringify(old?.coding) !== JSON.stringify(newConfig.coding)) {
      this.emit('coding', newConfig.coding);
    }

    this.emit('change', newConfig);
    console.log('[config-watcher] Config reloaded');
  }

  _reattach() {
    // File may have been replaced (atomic write). Try to re-attach after delay.
    if (this._watcher) { this._watcher.close(); this._watcher = null; }
    this._reattachTimer = setTimeout(() => {
      this._reattachTimer = null;
      try {
        if (fs.existsSync(CONFIG_PATH)) {
          this.start();
        }
      } catch {}
    }, 1000);
  }

  getConfig() { return this._lastConfig; }
}

module.exports = { ConfigWatcher };
