# frozen_string_literal: true

require 'json'

module GitlabQuality
  module TestTooling
    module TestMetric
      class LogTestMetrics
        include Concerns::TestMetrics
        include Concerns::InfluxdbTools

        CUSTOM_METRICS_KEY = :custom_test_metrics

        def initialize(examples:, influxdb_url: nil, influxdb_token: nil, influxdb_bucket: nil, run_type: nil)
          @examples = examples
          @influxdb_url = influxdb_url
          @influxdb_token = influxdb_token
          @influxdb_bucket = influxdb_bucket
          @run_type = run_type
        end

        # Push test execution metrics to influxdb
        #
        # @param [Array<String>] custom_keys_tags
        # @param [Array<String>] custom_keys_fields
        # @return [nil]
        def push_test_metrics(custom_keys_tags: nil, custom_keys_fields: nil)
          @test_metrics ||= examples.filter_map { |example| parse_test_results(example, custom_keys_tags, custom_keys_fields) }

          write_api(url: influxdb_url, token: influxdb_token, bucket: influxdb_bucket).write(data: test_metrics)
          Runtime::Logger.debug("Pushed #{test_metrics.length} test execution entries to influxdb")
        rescue StandardError => e
          Runtime::Logger.error("Failed to push test execution metrics to influxdb, error: #{e}")
        end

        # Save metrics in json file
        #
        # @param [String] file_name
        # @param [Array<String>] custom_keys_tags
        # @param [Array<String>] custom_keys_fields
        # @return [nil]
        def save_test_metrics(file_name, custom_keys_tags: nil, custom_keys_fields: nil)
          @test_metrics ||= examples.filter_map { |example| parse_test_results(example, custom_keys_tags, custom_keys_fields) }
          file = "tmp/#{file_name}"

          File.write(file, test_metrics.to_json) && Runtime::Logger.debug("Saved test metrics to #{file}")
        rescue StandardError => e
          Runtime::Logger.error("Failed to save test execution metrics, error: #{e}")
        end

        private

        attr_reader :examples, :test_metrics, :influxdb_url, :influxdb_token, :influxdb_bucket, :run_type

        # Transform example to influxdb compatible metrics data
        # https://github.com/influxdata/influxdb-client-ruby#data-format
        #
        # @param [RSpec::Core::Example] example
        # @param [Array<String>] custom_keys_tags
        # @param [Array<String>] custom_keys_fields
        # @return [Hash]
        def parse_test_results(example, custom_keys_tags, custom_keys_fields)
          {
            name: 'test-stats',
            time: time,
            tags: tags(example, custom_keys_tags, run_type),
            fields: fields(example, custom_keys_fields)
          }
        rescue StandardError => e
          Runtime::Logger.error("Failed to transform example '#{example.id}', error: #{e}")
          nil
        end
      end
    end
  end
end