class LHC::Auth

def after_response

def after_response
  return unless configuration_correct?
  return unless reauthenticate?
  reauthenticate!
end

def auth_options

def auth_options
  request.options[:auth] || {}
end

def basic_authentication!

def basic_authentication!
  auth = auth_options[:basic]
  credentials = "#{auth[:username]}:#{auth[:password]}"
  set_basic_authorization_header(Base64.strict_encode64(credentials).chomp)
end

def bearer_authentication!

def bearer_authentication!
  token = auth_options[:bearer]
  token = token.call if token.is_a?(Proc)
  set_bearer_authorization_header(token)
end

def bearer_header_present?

def bearer_header_present?
  @has_bearer_header ||= request.headers['Authorization'] =~ /^Bearer .+$/i
end

def before_raw_request

def before_raw_request
  body_authentication! if auth_options[:body]
end

def before_request

def before_request
  bearer_authentication! if auth_options[:bearer]
  basic_authentication! if auth_options[:basic]
end

def body_authentication!

def body_authentication!
  auth = auth_options[:body]
  request.options[:body] = (request.options[:body] || {}).merge(auth)
end

def configuration_correct?

def configuration_correct?
  # warn user about configs, only if refresh_client_token_option is set at all
  refresh_client_token_option && refresh_client_token? && retry_interceptor?
end

def reauthenticate!

def reauthenticate!
  # refresh token and update header
  token = refresh_client_token_option.call
  set_bearer_authorization_header(token)
  # trigger LHC::Retry and ensure we do not trigger reauthenticate!
  # again should it fail another time
  new_options = request.options.dup
  new_options = new_options.merge(retry: { max: 1 })
  new_options = new_options.merge(auth: { reauthenticated: true })
  request.options = new_options
end

def reauthenticate?

def reauthenticate?
  !response.success? &&
    !auth_options[:reauthenticated] &&
    bearer_header_present? &&
    LHC::Error.find(response) == LHC::Unauthorized
end

def refresh_client_token?

def refresh_client_token?
  return true if refresh_client_token_option.is_a?(Proc)
  warn("[WARNING] The given refresh_client_token must be a Proc for reauthentication.")
end

def refresh_client_token_option

def refresh_client_token_option
  @refresh_client_token_option ||= auth_options[:refresh_client_token] || refresh_client_token
end

def retry_interceptor?

def retry_interceptor?
  return true if all_interceptor_classes.include?(LHC::Retry) && all_interceptor_classes.index(LHC::Retry) > all_interceptor_classes.index(self.class)
  warn("[WARNING] Your interceptors must include LHC::Retry after LHC::Auth.")
end

def set_authorization_header(value)

rubocop:disable Naming/AccessorMethodName
def set_authorization_header(value)
  request.headers['Authorization'] = value
end

def set_basic_authorization_header(base_64_encoded_credentials)

def set_basic_authorization_header(base_64_encoded_credentials)
  request.options[:auth][:basic].merge!(base_64_encoded_credentials: base_64_encoded_credentials)
  set_authorization_header("Basic #{base_64_encoded_credentials}")
end

def set_bearer_authorization_header(token)

def set_bearer_authorization_header(token)
  request.options[:auth].merge!(bearer_token: token)
  set_authorization_header("Bearer #{token}")
end