module ThreeScale
  class RequestLogsSearch
    attr_accessor :code, :service_id, :application_id, :timestamp

    def initialize(code: nil, application_id: nil, timestamp: nil)
      @code           = code
      @application_id = application_id
      @timestamp      = timestamp
    end

    def to_hash
      instance_values.each_with_object({}) do |(key, value), hash|
        next if value.blank?

        if key == "code"
          hash["log"] = { "code" => code_to_query(value) }
        else
          hash[key] = value
        end
      end
    end

    # cubert-client uses Rack to compose url query params. There is a bug in
    # rack < v1.6.0 with nested query strings and integer values.
    # This project can't use rack v1.6.0 because rails 4.0 depends on rack v1.5
    # We should update to rails 4.2 to solve this issue.
    # Meanwhile, we can avoid it if we convert integer values to strings.
    # This explains the following weird code :-)

    def code_to_query(raw_code)
      return raw_code.to_s if raw_code.is_a?(Integer)
      codes = raw_code.split(",").map do |code|
        massage_code(code.strip)
      end

      (codes.size) > 1 ? codes : codes.first
    end

    def massage_code(code)
      if code =~ /\dXX\z/i
        code_to_range(code)
      elsif code =~ /\A\d/
        code
      else
        "0"
      end
    end

    def code_to_range(code)
      first_digit = code[0...1].to_i
      {
        "$gte" => "#{first_digit}00",
        "$lt"  => "#{first_digit + 1}00",
      }
    end
  end
end
