# frozen_string_literal: true

module Abaci
  class << self
    def error_rates
      @error_rates ||= Influx.pageviews.collect do |timestamp, pageview_count|
        error_count = Sentinel.errors[timestamp] || 0

        time_slice_data = {
          pageviews: pageview_count,
          errors: error_count,
          error_rate: error_count / pageview_count.to_f
        }

        [timestamp, time_slice_data]
      end.to_h
    end

    def error_rates_by_build
      @error_rates_by_build ||= Influx.pageviews_by_build.collect do |timestamp, builds|
        errors = Sentinel.errors_by_build[timestamp] || {}

        build_ids = (errors.keys + builds.keys).to_set

        time_slice_data = build_ids.collect do |build_id|
          pageview_count = builds[build_id] || 0
          error_count = errors[build_id] || 0

          build_data = {
            pageviews: pageview_count,
            errors: error_count,
            error_rate: pageview_count.zero? ? -1.0 : error_count / pageview_count.to_f
          }

          [build_id, build_data]
        end.to_h

        [timestamp, time_slice_data]
      end.to_h
    end

    # Takes a duration string like '3d5h' and converts it to the number of milliseconds 277_200_000
    # @param duration [String] string to parse into milliseconds
    # @return [Integer] millisecond length of the duration string
    def parse_duration(duration)
      duration.scan(/([\d.-]+)(ms|s|m|h|d)/).reduce(0) do |total, parsed_duration|
        number, unit = parsed_duration
        total + case unit
                  when 'ms'
                    number.to_i
                  when 's'
                    number.to_i * 1_000
                  when 'm'
                    number.to_i * 60_000
                  when 'h'
                    number.to_i * 3_600_000
                  when 'd'
                    number.to_i * 86_400_000
                  else
                    raise "Invalid unit type #{unit} found in duration string."
                end
      end
    end
  end
end