(ns auto-ap.datomic.users
  (:require
   [auto-ap.datomic :refer [conn]]
   [datomic.client.api :as dc]))

(defn add-arg [query name value where & rest]
  (let [query (-> query
                  (update :args conj value)
                  (update-in [:query :in] conj name)
                  (update-in [:query :where] conj where))]
    (reduce #(update-in %1 [:query :where] conj %2) query rest)))

(defn get-by-id [id]
  (let [query (-> {:query {:find ['(pull ?e [*
                                             {:user/clients [*]}
                                             {:user/role [:db/ident]}])]
                           :in ['$]
                           :where []}
                   :args [(dc/db conn)]}
                  (add-arg '?e id ['?e]))]
    (->> (dc/q query)
         (map first)
         (map #(update % :user/role :db/ident))
         first)))

(defn find-or-insert! [{:keys [:user/provider :user/provider-id] :as new-user}]
  (let [is-first-user?  (not (seq (dc/q {:query [:find '?e
                                                    :in '$
                                                    :where '[?e :user/provider]]
                                            :args [(dc/db conn)]})))
        user (some-> {:query [:find '(pull ?e [*
                                            {:user/clients [*]}
                                            {:user/role [:db/ident]}])
                          :in '$ '?provider '?provider-id
                          :where '[?e :user/provider ?provider]
                                  '[?e :user/provider-id ?provider-id]]
                  :args [(dc/db conn) provider provider-id]}
                 (dc/q)
                 first
                 first
                 (update :user/role :db/ident))]
    (if user
      user
      (let [new-user-trans (dc/transact conn {:tx-data [(cond-> new-user
                                                         true           (assoc :db/id "user")
                                                         is-first-user? (assoc :user/role :user-role/admin))]})]
        (get-by-id (-> new-user-trans :tempids (get "user")))))))

(defn raw-graphql [_]
  (let [query (cond-> {:query {:find ['(pull ?e [*
                                                 {:user/clients [*]}
                                                 {:user/role [:db/ident]}])]
                               :in ['$]
                               :where ['[?e :user/role]]}
                       :args [(dc/db conn)]})]
    
    (->> (dc/q query)
         (map first)
         (map #(update % :user/role :db/ident))
         )))

(defn sort-fn  [args]
  (cond
    (= "client" (:sort-by args))
    #(-> % :payment/client :client/name)

    :else
    (keyword "payment" (:sort-by args))))

(defn get-graphql [args]
  (let [results (raw-graphql args)]
    (cond->> results
      (:sort-by args) (sort-by (sort-fn args))
      (= (:asc args) false) (reverse)
      true (drop (:start args 0))
      true (take (:count args 500)))))

