# frozen_string_literal: true

require 'yaml'
require 'singleton'

# 客户端配置管理
class Settings
  include Singleton

  CONFIG_FILE = File.join(__dir__, '..', 'config', 'settings.yml')
  DEFAULT_CONFIG = {
    cloud_url: 'http://localhost:3000',
    api_token: nil,
    access_token: nil,
    access_token_expires_at: nil,
    database: {
      path: 'db/client.db',
      encryption_key: nil
    },
    execution: {
      max_concurrent_devices: 5,
      script_timeout: 300,
      retry_count: 3
    },
    logging: {
      level: 'info',
      max_file_size: '10MB',
      retention_days: 30
    },
    security: {
      require_startup_password: false,
      auto_lock_minutes: 30
    },
    ui: {
      language: 'zh-CN'
    },
    password_encryption_key: nil,
    custom_integration: {
      enabled: true,
      sync_on_startup: true,
      sync_before_script: true,
      sync_interval_hours: 1,
      cache_ttl_hours: 24,
      default_use_user_version: false,
      security: {
        enable_sandbox: true,
        validate_syntax: true,
        max_execution_time: 30
      },
      history: {
        max_entries: 20,
        keep_code_preview: true
      }
    }
  }.freeze

  def initialize
    @config = DEFAULT_CONFIG.dup
    load_config
  end

  def get(*keys)
    keys.inject(@config) do |memo, key|
      memo.is_a?(Hash) ? memo[key.to_sym] : nil
    end
  end

  def set(*keys, value)
    *path, final_key = keys
    target = path.inject(@config) { |memo, key| memo[key.to_sym] }
    target[final_key.to_sym] = value
    save_config
  end

  def api_token_configured?
    !get(:api_token).nil? && !get(:api_token).empty?
  end

  def save_api_token(token)
    set(:api_token, token)
    set(:access_token, nil)
    set(:access_token_expires_at, nil)
  end

  def save_cloud_url(url)
    set(:cloud_url, url)
    set(:access_token, nil)
    set(:access_token_expires_at, nil)
  end

  def clear_auth
    set(:api_token, nil)
    set(:access_token, nil)
    set(:access_token_expires_at, nil)
  end

  def root
    File.expand_path('..', __dir__)
  end

  def database_path
    File.expand_path(get(:database, :path), root)
  end

  def database_encryption_key
    key = get(:database, :encryption_key)
    if key.nil? || key.empty?
      require 'securerandom'
      key = SecureRandom.hex(32)
      set(:database, :encryption_key, key)
    end
    key
  end

  def max_concurrent_devices
    get(:execution, :max_concurrent_devices)
  end

  def script_timeout
    get(:execution, :script_timeout)
  end

  def retry_count
    get(:execution, :retry_count)
  end

  def password_encryption_key
    key = get(:password_encryption_key)
    if key.nil? || key.empty?
      require 'securerandom'
      key = SecureRandom.hex(32)
      set(:password_encryption_key, key)
    end
    key
  end

  def log_level
    get(:logging, :level)
  end

  private

  def load_config
    return unless File.exist?(CONFIG_FILE)

    yaml_config = YAML.load(File.read(CONFIG_FILE), symbolize_names: true)
    @config = deep_merge(@config, yaml_config)
  rescue StandardError => e
    puts "警告：无法加载配置文件 #{CONFIG_FILE}: #{e.message}"
  end

  def save_config
    File.write(CONFIG_FILE, @config.to_yaml)
  end

  def deep_merge(hash1, hash2)
    hash1.merge(hash2) do |_key, old_val, new_val|
      if old_val.is_a?(Hash) && new_val.is_a?(Hash)
        deep_merge(old_val, new_val)
      else
        new_val
      end
    end
  end
end

def settings
  Settings.instance
end
