module ZuoraConnect::Controllers::Helpers

def authenticate_app_api_request

def authenticate_app_api_request
  ZuoraConnect::AppInstance.read_master_db do
    #Skip session for api requests
    request.session_options[:skip] = true
    Thread.current[:appinstance] = nil
    if ZuoraConnect.logger.is_a?(Ougai::Logger); ZuoraConnect.logger.with_fields = {}; end
    if Rails.logger.is_a?(Ougai::Logger); Rails.logger.with_fields = {}; end
    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
    ZuoraConnect::ZuoraUser.current_user_id = request.headers["Zuora-User-Id"]
    if request.headers["API-Token"].present?
      @appinstance = ZuoraConnect::AppInstance.find_by(:api_token => request.headers["API-Token"])
      ZuoraConnect.logger.debug("API REQUEST - API token") if @appinstance.present?
      check_instance
    elsif ZuoraConnect::AppInstance::INTERNAL_HOSTS.include?(request.headers.fetch("HOST", nil)) && request.headers['zuora-host'].present?
      zuora_host, zuora_entity_id, zuora_instance_id = [request.headers['zuora-host'], (request.headers['zuora-entity-ids'] || "").gsub('-',''), request.headers['zuora-instance-id']]
      zuora_host_mapping = {'origin-gateway.sbx.auw2.zuora.com' => 'rest.apisandbox.zuora.com',  'origin-gateway.prod.auw2.zuora.com' => 'rest.zuora.com'}
      zuora_host = zuora_host_mapping[zuora_host] if zuora_host_mapping.keys.include?(zuora_host)
      #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", "instances": appinstances.map {|instance| instance.id }.sort }, 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.find_by(:token => password)
        @appinstance ||= ZuoraConnect::AppInstance.find_by(:api_token => password)
        ZuoraConnect.logger.debug("API REQUEST - Basic Auth") if @appinstance.present?
        check_instance
      end
    else
      check_instance
    end
  end
end