(ns auto-ap.routes.graphql
  (:require [auto-ap.routes.utils :refer [wrap-secure wrap-spec]]
            [auto-ap.graphql :as ql]
            [auto-ap.logging :refer [warn-event]]
            [buddy.auth :refer [throw-unauthorized]]
            [clojure.edn :as edn]
            [compojure.core :refer [GET POST PUT context defroutes
                                    wrap-routes]]
            [clojure.tools.logging :as log]))
(defn handle-graphql [{:keys [request-method query-params body edn-params method] :as r}]
  (when (= "none" (:user/role (:identity r)))
    (throw-unauthorized))

  (try
    (let [variables (some-> (query-params "variables")
                            edn/read-string)
          body (some-> r :body slurp)]
      {:status 200
       :body (pr-str (ql/query (:identity r) (if (= request-method :get) (query-params "query") body) variables ))
       :headers {"Content-Type" "application/edn"}})
    (catch Throwable e
      (log/info "here we are " (.getCause e))
      
      (if-let [result (:result (ex-data e))]
        (do (log/warn "Graphql Result error" e)
          {:status 400
           :body (pr-str result)
           :headers {"Content-Type" "application/edn"}})
        (if-let [message (:validation-error (ex-data (.getCause e)) )]
          (do 
            (warn-event "GraphQL Validation error" {:message message
                                                    :data e})
            {:status 400
             :body (pr-str {:errors [{:message message}]})
             :headers {"Content-Type" "application/edn"}})
          (do (log/error "GraphQL error" e)
              {:status 500
               :body (pr-str {:errors [{:message (str "Unhandled error:" (str e))}]})
               :headers {"Content-Type" "application/edn"}}))))))


(defroutes routes
  (wrap-routes
   (context "/graphql" []
            (GET "/"  x (handle-graphql x))
            (POST "/"  x (handle-graphql x)))
   wrap-secure))
