'use strict';

/**
 * Fabius Configuration Manager
 * 
 * Handles reading/writing configuration, with sensible defaults.
 * Config is stored as JSON in the Fabius data directory.
 */

const fs = require('fs');
const path = require('path');
const os = require('os');

const DEFAULTS = {
  ai: {
    provider: 'mistral',
    apiKey: '',
    model: {
      classification: '',   // Uses provider defaults if empty
      codeGeneration: '',
      analysis: '',
    },
    temperature: 0.1,
    maxTokens: 4096,
    timeout: 30000,
    fallbackProvider: '',
    fallbackApiKey: '',
  },
  sources: {
    pollInterval: 1800,       // 30 minutes default
    defaultSources: true,     // Load pre-configured sources on first run
  },
  scanning: {
    maxDepth: 10,
    scanExtensions: ['.js', '.ts', '.mjs', '.cjs', '.jsx', '.tsx'],
    skipDirs: ['node_modules', '.git', '.next', 'dist', 'build', '.cache', 'coverage'],
    fileSizeLimit: 5 * 1024 * 1024,  // 5MB
  },
  remediation: {
    autoApply: false,
    autoApplyTrustedOnly: true,
    autoApplyMaxSeverity: 'high',
    notifyOnAutoApply: true,
    createBackup: true,
    backupDir: '.fabius/backups',
  },
  notifications: {
    enabled: true,
    trustedSourceAlert: true,     // Popup for trusted sources
    untrustedSourceBadge: true,   // Badge-only for untrusted
    scanComplete: true,
    scanCompleteClean: false,     // Don't notify on clean scans
  },
  scheduler: {
    enabled: true,
    intelPollInterval: 1800000,    // 30 min (ms)
    fullScanInterval: 86400000,    // 24h (ms)
    updateCheckInterval: 21600000, // 6h (ms)
  },
  ui: {
    theme: 'dark',
    startMinimized: true,
    minimizeToTray: true,
    language: 'en',
  },
  sync: {
    enabled: false,
    apiUrl: 'https://api.fabius.euphile.eu',
  },
};

class Config {
  /**
   * @param {string} configDir - Directory to store config (default: APPDATA/Fabius)
   */
  constructor(configDir) {
    this.configDir = configDir || path.join(
      process.env.APPDATA || path.join(os.homedir(), '.config'),
      'Fabius'
    );
    this.configPath = path.join(this.configDir, 'config.json');
    this.config = null;

    this._load();
  }

  _load() {
    try {
      if (fs.existsSync(this.configPath)) {
        const raw = fs.readFileSync(this.configPath, 'utf-8');
        const userConfig = JSON.parse(raw);
        this.config = this._deepMerge(DEFAULTS, userConfig);
      } else {
        this.config = JSON.parse(JSON.stringify(DEFAULTS));
      }
    } catch (err) {
      console.warn(`[Fabius Config] Failed to load config: ${err.message}. Using defaults.`);
      this.config = JSON.parse(JSON.stringify(DEFAULTS));
    }
  }

  save() {
    try {
      if (!fs.existsSync(this.configDir)) {
        fs.mkdirSync(this.configDir, { recursive: true });
      }
      fs.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2), 'utf-8');
    } catch (err) {
      console.error(`[Fabius Config] Failed to save config: ${err.message}`);
    }
  }

  /**
   * Get a config value by dot-separated path
   * @param {string} key - e.g., 'ai.provider' or 'remediation.autoApply'
   * @param {*} fallback - Fallback value if key doesn't exist
   */
  get(key, fallback = undefined) {
    const parts = key.split('.');
    let val = this.config;
    for (const part of parts) {
      if (val == null || typeof val !== 'object') return fallback;
      val = val[part];
    }
    return val !== undefined ? val : fallback;
  }

  /**
   * Set a config value by dot-separated path
   * @param {string} key
   * @param {*} value
   */
  set(key, value) {
    const parts = key.split('.');
    let obj = this.config;
    for (let i = 0; i < parts.length - 1; i++) {
      if (!obj[parts[i]] || typeof obj[parts[i]] !== 'object') {
        obj[parts[i]] = {};
      }
      obj = obj[parts[i]];
    }
    obj[parts[parts.length - 1]] = value;
    this.save();
  }

  /**
   * Get all config as flat object
   */
  getAll() {
    return JSON.parse(JSON.stringify(this.config));
  }

  /**
   * Reset config to defaults
   */
  reset() {
    this.config = JSON.parse(JSON.stringify(DEFAULTS));
    this.save();
  }

  /**
   * Get the data directory (for DB, logs, etc.)
   */
  getDataDir() {
    return this.configDir;
  }

  /**
   * Get the database path
   */
  getDbPath() {
    return path.join(this.configDir, 'fabius.db');
  }

  /**
   * Get the machine config path
   */
  getMachinePath() {
    return path.join(this.configDir, 'machine.json');
  }

  _deepMerge(defaults, overrides) {
    const result = {};
    for (const key of Object.keys(defaults)) {
      if (
        defaults[key] !== null &&
        typeof defaults[key] === 'object' &&
        !Array.isArray(defaults[key]) &&
        overrides[key] !== null &&
        typeof overrides[key] === 'object' &&
        !Array.isArray(overrides[key])
      ) {
        result[key] = this._deepMerge(defaults[key], overrides[key]);
      } else if (overrides.hasOwnProperty(key)) {
        result[key] = overrides[key];
      } else {
        result[key] = defaults[key];
      }
    }
    // Carry over keys from overrides not in defaults
    for (const key of Object.keys(overrides)) {
      if (!defaults.hasOwnProperty(key)) {
        result[key] = overrides[key];
      }
    }
    return result;
  }
}

Config.DEFAULTS = DEFAULTS;

module.exports = Config;
