module ZuoraConnect::Controllers::Helpers

def authenticate_app_api_request

def authenticate_app_api_request
  #Skip session for api requests
  Thread.current[:appinstance] = nil
  request.session_options[:skip] = true
  if defined?(ElasticAPM) && ElasticAPM.running?
    if ElasticAPM.respond_to?(:set_label)
      ElasticAPM.set_label(:trace_id, request.uuid) if defined?(ElasticAPM) && ElasticAPM.running?
    else
      ElasticAPM.set_label(:trace_id, request.uuid) if defined?(ElasticAPM) && ElasticAPM.running?
    end
  end
  start_time = Time.now
  if request.headers["API-Token"].present?
    @appinstance = ZuoraConnect::AppInstance.where(:api_token => request.headers["API-Token"]).first
    ZuoraConnect.logger.debug("[#{@appinstance.id}] API REQUEST - API token") if @appinstance.present?
    check_instance
  elsif ZuoraConnect::AppInstance::INTERNAL_HOSTS.include?(request.headers.fetch("HOST", nil))
    zuora_host, zuora_entity_id, zuora_instance_id = [request.headers['zuora-host'], (request.headers['zuora-entity-ids'] || "").gsub('-',''), request.headers['zuora-instance-id']]
    #Validate host present
    if zuora_host.blank?
      render json: {"status": 401, "message": "zuora-host header was not supplied."}, status: :unauthorized
      return
    end
    #Validate entity-ids present
    if zuora_entity_id.blank?
      render json: {"status": 401, "message": "zuora-entity-ids header was not supplied."}, status: :unauthorized
      return
    end
    #Select with instance id if present. Used where mulitple deployments are done.
    if zuora_instance_id.present?
      appinstances = ZuoraConnect::AppInstance.where("zuora_entity_ids ?& array[:entities] = true AND zuora_domain = :host AND id = :id", entities: [zuora_entity_id], host: zuora_host, id: zuora_instance_id.to_i)
    else
      appinstances = ZuoraConnect::AppInstance.where("zuora_entity_ids ?& array[:entities] = true AND zuora_domain = :host", entities: [zuora_entity_id], host: zuora_host)
    end
    if appinstances.size == 0
      render json: {"status": 401, "message": "Missing mapping or no deployment for '#{zuora_host}-#{zuora_entity_id}' ."}, status: :unauthorized
      return
    elsif appinstances.size > 1
      render json: {"status": 401, "message": "More than one app instance binded to host and entity ids. Please indicate correct instance via 'zuora-instance-id' header"}, status: :unauthorized
      return
    else
      @appinstance = appinstances.first
      check_instance
    end

  elsif request.headers.fetch("Authorization", "").include?("Basic ")
    authenticate_or_request_with_http_basic do |username, password|
      @appinstance = ZuoraConnect::AppInstance.where(:token => password).first
      @appinstance ||= ZuoraConnect::AppInstance.where(:api_token => password).first
      ZuoraConnect.logger.debug("[#{@appinstance.id}] API REQUEST - Basic Auth") if @appinstance.present?
      check_instance
    end
  else
    check_instance
  end
  
  if @appinstance.present?
    ZuoraConnect.logger.debug("[#{@appinstance.id}] Authenticate App API Request Completed In - #{(Time.now - start_time).round(2)}s")
  end
end