require 'resque-retry'

# to get retries working do:
# $ bundle exec rake resque:scheduler VERBOSE=true
# and
# $ bundle exec rake resque:work QUEUE=* VERBOSE=true

class WebHookJob
  extend ThreeScale::Analytics::ResquePlugin # to flush any analytics calls

  class Error < ::StandardError; end

  class ClientError < Error;
    def initialize(client_error)
      @client_error = client_error
    end

    def message
      @client_error.message
    end
  end

  extend Resque::Plugins::Retry

  @queue = :web_hooks

  @retry_limit = 5
  @retry_delay = Rails.env.development? ? 1.second : 1.minute # between retries

  def self.perform(id, provider_id, url, xml, content_type)
    logger.info { "Running WebHook(#{retry_identifier(id)}) (#{retry_attempt}/#{retry_limit})" }

    push(url, xml, content_type)
  rescue => exception
    handle_failure(exception, id, provider_id, url, xml)
  end

  def self.push(url, xml, content_type = nil)
    if content_type
      RestClient.post(url, xml, :content_type => content_type)
    else
      # kii
      RestClient.post(url, :params => { :xml => xml })
    end

  rescue SocketError, RestClient::Exception
    # Normally, we would just ignore the client side errors but we
    # need a Resque job to fail and then retry so it has to crash
    # hard.
    #
    # Nonetheless, the exception is wrapped so that it can be
    # ignored by Airbrake.
    #
    raise WebHookJob::ClientError.new($!)
  end

  def self.logger
    Rails.logger
  end

  def self.handle_failure(exception, id, provider_id, *args)
    wh = "WebHook(#{retry_identifier(id)})"
    logger.info { "#{wh} attempt ##{retry_attempt} failed with #{exception}" }

    # raise exception only when job will be retried
    # on last retry don't raise exception, because it would save it
    # to failures queue
    if retry_criteria_valid?(exception, *args)
      logger.info { "Retrying #{wh}" }
      raise exception
    else
      WebHookFailures.add(provider_id, exception, id, *args)
      logger.info { "#{wh} added to failures" }
    end
  end

  def self.retry_identifier(id, *)
    id
  end

end
