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

(defn <-datomic [results]
  (->> results
       (map first)
       (map #(update % :payment/date c/from-date))
       (map #(update % :payment/status :db/ident))
       (map #(update % :payment/type :db/ident))
       (map #(rename-keys % {:invoice-payment/_payment :payment/invoices}))))

(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)))

(def default-read '(pull ?e [*
                             {:invoice-payment/_payment [* {:invoice-payment/invoice [*]}]}
                             {:payment/client [:client/name :db/id :client/code]}
                             {:payment/bank-account [*]}
                             {:payment/vendor [:vendor/name :vendor/default-expense-account :db/id {:vendor/primary-contact [*]} {:vendor/address [*]}]}
                             {:payment/status [:db/ident]}
                             {:payment/type [:db/ident]}]))

(defn raw-graphql [args]
  (let [query (cond-> {:query {:find [default-read]
                               :in ['$]
                               :where ['[?e :payment/client]]}
                       :args [(d/db (d/connect uri))]}

                (limited-clients (:id args)) (add-arg '[?xx ...] (set (map :db/id (limited-clients (:id args))))
                                                      '[?e :payment/client ?xx])

                (:client-id args) (add-arg '?client-id (:client-id args)
                                              '[?e :payment/client ?client-id])
                (:client-code args) (add-arg '?client-code (:client-code args)
                                             '[?e :payment/client ?client-id]
                                             '[?client-id :client/code ?client-code] )
                (:vendor-id args) (add-arg '?vendor-id (:vendor-id args)
                                           '[?e :payment/vendor ?vendor-id])
                (:original-id args) (add-arg '?original-id (cond-> (:original-id args) (string? (:original-id args)) Long/parseLong )
                                           '[?e :payment/client ?c]
                                           '[?c :client/original-id ?original-id])
                (:check-number args) (add-arg '?check-number (:check-number args)
                                              '[?e :payment/check-number ?check-number])
                (:bank-account-id  args) (add-arg '?bank-account-id (:bank-account-id args)
                                                  '[?e :payment/bank-account ?bank-account-id])
                (:amount args) (add-arg '?amount (:amount args)
                                        '[?e :payment/amount ?amount])
                (:status args) (add-arg '?status (:status args)
                                        '[?e :payment/status ?status]))]
    
    (->> (d/query
          query)
         (<-datomic))))

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

    (= "vendor" (:sort-by args))
    #(-> % :payment/vendor :vendor/name (or "") (.toLowerCase ))

    :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)))

(defn get-by-id [id]
  (->> 
   (d/query (-> {:query {:find [default-read]
                         :in ['$]
                         :where []}
                 :args [(d/db (d/connect uri))]}
                (add-arg '?e id ['?e])))
   (<-datomic)   
   (first)))
