module Carto
  class OverquotaUsersService

    include ::LoggerHelper

    def initialize(date = Date.today)
      @date = date
    end

    def store_overquota_users(delta)
      overquota(delta).each do |user|
        $users_metadata.hmset(date_key, user.id, user.data.to_json)
      end
      # Expire the cache after two months. Enough time to review data if needed
      $users_metadata.expire(date_key, 2.months)
    end

    def get_stored_overquota_users
      if $users_metadata.exists(date_key)
        $users_metadata.hgetall(date_key).values.map { |v| JSON.parse(v) }
      else
        log_warning(message: 'There is no overquota cached users for date', date_string: formatted_date)
        []
      end
    end

    private

    def date_key
      "overquota:users:#{formatted_date}"
    end

    def formatted_date
      @date.strftime('%Y%m%d')
    end

    ##
    # SLOW! Checks redis data (geocodings and isolines) for every user
    # delta: get users who are also this percentage below their limit.
    #        example: 0.20 will get all users at 80% of their map view limit
    #
    def overquota(delta)
      overquota_users = []
      ::User.where(enabled: true, organization_id: nil).use_cursor.each do |u|
        overquota_users << u if services_overquota(u, delta)
      end
      overquota_users
    end

    SERVICES = %w(geocoding twitter_datasource here_isolines mapzen_routing).freeze
    def services_overquota(user, delta)
      SERVICES.any? do |service|
        user.send("get_#{service}_calls") > user.send("#{service}_quota").to_i * (1 - delta)
      end
    end
  end
end
