// Config Manager - Dynamic configuration management
// Supports local and server-based configuration
// Enables feature flags, threshold tuning, and A/B testing

export class ConfigManager {
  constructor() {
    this.config = {};
    this.defaults = this.getDefaultConfig();
    this.serverUrl = null;
    this.syncInterval = null;
    this.listeners = new Set();
  }

  /**
   * Get default configuration
   * @returns {object} - Default config object
   */
  getDefaultConfig() {
    return {
      // Risk scoring thresholds
      thresholds: {
        critical: 10,
        high: 7,
        medium: 4,
        low: 2
      },

      // Detector weights (multipliers for risk scoring)
      weights: {
        domainReputation: 2,
        pathAnalysis: 1,
        parameterAnalysis: 1,
        extensionAnalysis: 2,
        mimeTypeAnalysis: 2,
        permissionAnalysis: 3,
        clipboardDetection: 3,
        formDetection: 2
      },

      // Feature flags
      features: {
        newAnalyzerEngine: true,          // Use new analyzer architecture
        clipboardProtection: true,
        urlAnalysis: true,
        domAnalysis: true,
        resourceBlocking: true,
        permissionMonitoring: true,
        telemetryEnabled: false,          // Enterprise telemetry
        policyEnforcement: false,         // Enterprise policy
        mdmIntegration: false,            // MDM integration
        siemIntegration: false            // SIEM integration
      },

      // Performance settings
      performance: {
        cacheSize: 10000,                 // LRU cache size
        maxAnalysisTime: 100,             // Max analysis time (ms)
        parallelDetectors: 4,             // Max parallel detector execution
        earlyExit: true,                  // Exit on critical risk
        bypassCache: false                // Bypass cache for testing
      },

      // Telemetry settings
      telemetry: {
        enabled: false,
        endpoint: null,
        batchSize: 100,
        flushInterval: 60000,             // 60 seconds
        includeMetrics: true,
        includePII: false                 // Never include PII
      },

      // Policy settings
      policy: {
        enabled: false,
        defaultAction: 'warn',            // warn, block, allow
        auditEnabled: false,
        auditEndpoint: null
      },

      // Enterprise settings
      enterprise: {
        mdmEnabled: false,
        adminConsoleUrl: null,
        siemEndpoint: null,
        siemFormat: 'cef',                // cef or json
        configSyncInterval: 3600000       // 1 hour
      },

      // Detector-specific settings
      detectors: {
        // Each detector can have custom config
      },

      // UI settings
      ui: {
        showDetailedAlerts: true,
        showStats: true,
        theme: 'auto'                     // auto, light, dark
      },

      // Version
      version: '1.0.0'
    };
  }

  /**
   * Load configuration
   * @param {string} source - Source: 'default', 'local', 'server'
   * @param {object} options - Load options
   */
  async loadConfig(source = 'local', options = {}) {
    try {
      let loadedConfig = {};

      switch (source) {
        case 'default':
          loadedConfig = this.defaults;
          break;

        case 'local':
          const stored = await chrome.storage.local.get('config');
          loadedConfig = stored.config || this.defaults;
          break;

        case 'server':
          if (!options.serverUrl) {
            throw new Error('Server URL required for server config');
          }
          loadedConfig = await this.loadFromServer(options.serverUrl);
          break;

        default:
          console.warn(`[ConfigManager] Unknown source: ${source}, using defaults`);
          loadedConfig = this.defaults;
      }

      // Merge with defaults (preserve defaults for missing keys)
      this.config = this.mergeConfig(this.defaults, loadedConfig);

      // Save to local storage
      await this.saveToLocal();

      console.log(`[ConfigManager] Config loaded from ${source}`);
      this.notifyListeners('config-loaded', this.config);

      return this.config;
    } catch (error) {
      console.error('[ConfigManager] Failed to load config:', error);
      this.config = this.defaults;
      return this.defaults;
    }
  }

  /**
   * Load configuration from server (enterprise)
   * @param {string} serverUrl - Server URL
   * @returns {object} - Server config
   */
  async loadFromServer(serverUrl) {
    try {
      const response = await fetch(`${serverUrl}/api/config/current`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
          'X-Extension-Version': chrome.runtime.getManifest().version
        }
      });

      if (!response.ok) {
        throw new Error(`Server returned ${response.status}`);
      }

      const data = await response.json();
      this.serverUrl = serverUrl;

      console.log('[ConfigManager] Loaded config from server');
      return data.config || {};
    } catch (error) {
      console.error('[ConfigManager] Failed to load from server:', error);
      throw error;
    }
  }

  /**
   * Start automatic config sync (enterprise)
   * @param {string} serverUrl - Server URL
   * @param {number} interval - Sync interval (ms)
   */
  startSync(serverUrl, interval = null) {
    this.serverUrl = serverUrl;
    const syncInterval = interval || this.config.enterprise?.configSyncInterval || 3600000;

    // Clear existing interval
    if (this.syncInterval) {
      clearInterval(this.syncInterval);
    }

    // Set up periodic sync
    this.syncInterval = setInterval(async () => {
      try {
        console.log('[ConfigManager] Syncing config from server...');
        await this.loadConfig('server', { serverUrl });
      } catch (error) {
        console.error('[ConfigManager] Config sync failed:', error);
      }
    }, syncInterval);

    console.log(`[ConfigManager] Started config sync (interval: ${syncInterval}ms)`);
  }

  /**
   * Stop automatic config sync
   */
  stopSync() {
    if (this.syncInterval) {
      clearInterval(this.syncInterval);
      this.syncInterval = null;
      console.log('[ConfigManager] Stopped config sync');
    }
  }

  /**
   * Save configuration to local storage
   */
  async saveToLocal() {
    try {
      await chrome.storage.local.set({ config: this.config });
      console.log('[ConfigManager] Config saved to local storage');
    } catch (error) {
      console.error('[ConfigManager] Failed to save config:', error);
    }
  }

  /**
   * Get configuration value
   * @param {string} path - Dot-notation path (e.g., 'thresholds.high')
   * @param {any} defaultValue - Default value if not found
   * @returns {any} - Config value
   */
  get(path, defaultValue = null) {
    const keys = path.split('.');
    let value = this.config;

    for (const key of keys) {
      if (value && typeof value === 'object' && key in value) {
        value = value[key];
      } else {
        return defaultValue;
      }
    }

    return value;
  }

  /**
   * Set configuration value
   * @param {string} path - Dot-notation path
   * @param {any} value - Value to set
   * @param {boolean} persist - Save to local storage
   */
  async set(path, value, persist = true) {
    const keys = path.split('.');
    let current = this.config;

    // Navigate to parent
    for (let i = 0; i < keys.length - 1; i++) {
      const key = keys[i];
      if (!(key in current) || typeof current[key] !== 'object') {
        current[key] = {};
      }
      current = current[key];
    }

    // Set value
    const lastKey = keys[keys.length - 1];
    const oldValue = current[lastKey];
    current[lastKey] = value;

    console.log(`[ConfigManager] Set ${path} = ${JSON.stringify(value)}`);

    // Persist if requested
    if (persist) {
      await this.saveToLocal();
    }

    // Notify listeners
    this.notifyListeners('config-changed', { path, value, oldValue });
  }

  /**
   * Set threshold
   * @param {string} riskLevel - Risk level (critical, high, medium, low)
   * @param {number} value - Threshold value
   */
  async setThreshold(riskLevel, value) {
    await this.set(`thresholds.${riskLevel}`, value);
  }

  /**
   * Set feature flag
   * @param {string} feature - Feature name
   * @param {boolean} enabled - Enable state
   */
  async setFeature(feature, enabled) {
    await this.set(`features.${feature}`, enabled);
  }

  /**
   * Enable/disable telemetry
   * @param {boolean} enabled - Enable state
   */
  async setTelemetry(enabled) {
    await this.set('telemetry.enabled', enabled);
    await this.set('features.telemetryEnabled', enabled);
  }

  /**
   * Merge two config objects
   * @param {object} defaults - Default config
   * @param {object} overrides - Override config
   * @returns {object} - Merged config
   */
  mergeConfig(defaults, overrides) {
    const merged = { ...defaults };

    for (const key in overrides) {
      if (overrides[key] && typeof overrides[key] === 'object' && !Array.isArray(overrides[key])) {
        // Recursively merge objects
        merged[key] = this.mergeConfig(merged[key] || {}, overrides[key]);
      } else {
        // Override primitive values and arrays
        merged[key] = overrides[key];
      }
    }

    return merged;
  }

  /**
   * Reset to defaults
   */
  async resetToDefaults() {
    this.config = { ...this.defaults };
    await this.saveToLocal();
    console.log('[ConfigManager] Reset to defaults');
    this.notifyListeners('config-reset', this.config);
  }

  /**
   * Export configuration as JSON
   * @returns {string} - JSON string
   */
  export() {
    return JSON.stringify(this.config, null, 2);
  }

  /**
   * Import configuration from JSON
   * @param {string} json - JSON string
   */
  async import(json) {
    try {
      const imported = JSON.parse(json);
      this.config = this.mergeConfig(this.defaults, imported);
      await this.saveToLocal();
      console.log('[ConfigManager] Imported config');
      this.notifyListeners('config-imported', this.config);
      return true;
    } catch (error) {
      console.error('[ConfigManager] Failed to import config:', error);
      return false;
    }
  }

  /**
   * Register config change listener
   * @param {function} callback - Callback function (event, data)
   */
  addListener(callback) {
    this.listeners.add(callback);
  }

  /**
   * Remove config change listener
   * @param {function} callback - Callback function
   */
  removeListener(callback) {
    this.listeners.delete(callback);
  }

  /**
   * Notify all listeners
   * @param {string} event - Event name
   * @param {any} data - Event data
   */
  notifyListeners(event, data) {
    for (const listener of this.listeners) {
      try {
        listener(event, data);
      } catch (error) {
        console.error('[ConfigManager] Listener error:', error);
      }
    }
  }

  /**
   * Get all configuration
   * @returns {object} - Full config object
   */
  getAll() {
    return { ...this.config };
  }

  /**
   * Get config summary for display
   * @returns {object} - Summary
   */
  getSummary() {
    return {
      version: this.config.version,
      featuresEnabled: Object.entries(this.config.features || {})
        .filter(([_, enabled]) => enabled)
        .map(([name, _]) => name),
      thresholds: this.config.thresholds,
      telemetryEnabled: this.config.telemetry?.enabled || false,
      policyEnabled: this.config.policy?.enabled || false,
      serverUrl: this.serverUrl,
      lastSync: this.lastSyncTime || null
    };
  }
}
