# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
# frozen_string_literal: true

require 'contrast/config/effective_config_value'

module Contrast
  module Agent
    module DiagnosticsConfig
      # The current effective config received from all authorized configuration channels.
      class EffectiveConfig
        # Value of effective agent configurations
        #
        # @return [Array]
        attr_reader :values

        def initialize
          @values = []
        end

        def to_controlled_hash
          {
              EffectiveConfig: { values: @values&.map(&:to_controlled_hash) },
              File: yaml_config_settings,
              Environment: environment_settings,
              CommandLine: command_line_settings,
              ContrastUI: contrast_ui_settings
          }
        end

        private

        def yaml_config_settings
          {
              Path: Contrast::CONFIG.config_file_path,
              Values: Contrast::CONFIG.sources.for(Contrast::Components::Config::Sources::YAML)
          }
        end

        def command_line_settings
          flatten_settings(Contrast::CONFIG.sources.for(Contrast::Components::Config::Sources::CLI))
        end

        def contrast_ui_settings
          flatten_settings(Contrast::CONFIG.sources.for(Contrast::Components::Config::Sources::CONTRASTUI))
        end

        def flatten_settings data, path = []
          data.each_with_object([]) do |(k, v), entries|
            if v.cs__is_a?(Hash)
              entries.concat(flatten_settings(v, path.dup.append(k.to_sym)))
            else
              entries << { "#{ path.join('.') }.#{ k }" => Contrast::CONFIG.config.loaded_config.dig(*path, k) }
            end
          end.flatten # rubocop:disable Style/MethodCalledOnDoEndBlock
        end

        def environment_settings
          ENV.select { |e| e.to_s.start_with?(Contrast::Components::Config::CONTRAST_ENV_MARKER) }.
              to_a.
              map { |e| Hash[*e] }
        end
      end
    end
  end
end