(ns auto-ap.datomic.users
  (:require [datomic.api :as d]
            [auto-ap.datomic :refer [uri]]
            [clojure.set :refer [rename-keys]]
            [clj-time.coerce :as c]))

(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 [(d/db (d/connect uri))]}
                  (add-arg '?e id ['?e])
                  (doto println))]
    
    (->> (d/query query)
         (map first)
         (map #(update % :user/role :db/ident))
         first)))

(defn find-or-insert! [{:keys [:user/provider :user/provider-id] :as new-user}]
  (let [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 [(d/db (d/connect uri)) provider provider-id]}
                 (d/query)
                 first
                 first
                 (update :user/role :db/ident))]
    (if user
      user
      (let [new-user-trans @(d/transact (d/connect uri) [(assoc new-user :db/id "user")])]
        (println new-user-trans)
        (get-by-id (-> new-user-trans :tempids (get "user")))))))

(defn raw-graphql [args]
  (let [query (cond-> {:query {:find ['(pull ?e [*
                                                 {:user/clients [*]}
                                                 {:user/role [:db/ident]}])]
                               :in ['$]
                               :where ['[?e :user/role]]}
                       :args [(d/db (d/connect uri))]})]
    
    (->> (d/query 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 100)))))

(defn count-graphql [args]
  
  (->> (raw-graphql args)
       (count)))
