class GraphqlController < ApplicationController
  include FeatureFlags

  feature_flag :graphql_api

  skip_before_action :verify_authenticity_token
  skip_authorization_check

  class QueryStringError < StandardError; end

  def execute
    raise GraphqlController::QueryStringError if query_string.nil?

    result = ConsulSchema.execute(
      query_string,
      variables: prepare_variables,
      context: {},
      operation_name: params[:operationName]
    )
    render json: result
  rescue GraphqlController::QueryStringError
    render json: { message: "Query string not present" }, status: :bad_request
  rescue JSON::ParserError
    render json: { message: "Error parsing JSON" }, status: :bad_request
  rescue GraphQL::ParseError
    render json: { message: "Query string is not valid JSON" }, status: :bad_request
  rescue ArgumentError => e
    render json: { message: e.message }, status: :bad_request
  end

  private

    def query_string
      if request.headers["CONTENT_TYPE"] == "application/graphql"
        request.body.string
      else
        params[:query]
      end
    end

    # Handle variables in URL query string and JSON body
    def prepare_variables
      case variables_param = params[:variables]
      # URL query string
      when String
        if variables_param.present?
          JSON.parse(variables_param) || {}
        else
          {}
        end
      # JSON object in request body gets converted to ActionController::Parameters
      when ActionController::Parameters
        variables_param.to_unsafe_hash # GraphQL-Ruby will validate name and type of incoming variables.
      when nil
        {}
      else
        raise ArgumentError, "Unexpected parameter: #{variables_param}"
      end
    end
end
