(ns make-ledger-fast-again
  (:require [datomic.api :as d]
            [auto-ap.datomic :refer[uri]]
            [auto-ap.utils :refer [by]]
            [clj-time.coerce :as coerce]

            ))


(time 
 (def old-results 
   (map (fn [o] (update o :amount int)) (:balance_sheet_accounts (auto-ap.graphql.ledger/get-balance-sheet nil {:client_id 17592186046483
                                                                                :date (coerce/to-date-time #inst "2020-09-01")} nil)))))


#_(defn roll-up-2 [jes]
  )


(def new-results 
  (let [client-id 17592186046483
        brackets [#inst "2019-01-01" #inst "2020-01-01"]
        accounts (by :db/id (map first (d/query {:query {:find ['(pull ?e [:db/id :account/name
                                                                           :account/numeric-code
                                                                           {:account/type [:db/ident]
                                                                            :account/client-overrides [:account-client-override/client :account-client-override/name]}
                                                                           ])]
                                                         :in ['$]
                                                         :where ['[?e :account/name]]}
                                                 :args [(d/db (d/connect uri) )]})))

        bank-accounts (by :db/id (map first (d/query {:query {:find ['(pull ?e [:db/id :bank-account/name {:bank-account/type [:db/ident]}])]
                                                              :in ['$]
                                                              :where ['[?e :bank-account/name]]}
                                                      :args [(d/db (d/connect uri))]})))  
        
        overrides-by-client (->> accounts
                                 vals
                                 (mapcat (fn [a]
                                           (map (fn [o]
                                                  [[[(:db/id a) (:db/id (:account-client-override/client o))]]
                                                   (:account-client-override/name o)])
                                                (:account/client-overrides a))
                                           ) )
                                 (into {} ))
        account->name (fn [a]
                        (or (:bank-account/name (bank-accounts a))
                            (overrides-by-client [a client-id])
                            (:account/name (accounts a))))

        account->numeric-code (fn [a]
                                (or (:account/numeric-code (accounts a))
                                    (and (#{:bank-account-type/check} (:db/ident (:bank-account/type (bank-accounts a))))
                                         11100)
                                    (and (#{:bank-account-type/credit} (:db/ident (:bank-account/type (bank-accounts a))))
                                         28000)))
        account->type (fn [a]
                        (or (:db/ident (:account/type (accounts a)))
                            ({:bank-account-type/check :account-type/asset
                              :bank-account-type/credit :account-type/liability}
                             (:db/ident (:bank-account/type (bank-accounts a))))))
        all-ledger-entries (->> (d/query 
                                 {:query {:find ['?d '?jel '?account '?location '?debit '?credit ]
                                          :in ['$ '?client-id]
                                          :where ['[?e :journal-entry/client ?client-id]
                                                  '[?e :journal-entry/date ?d]
                                                  '[(<= ?d #inst "2020-09-01")]
                                                  '[?e :journal-entry/line-items ?jel]
                                                  '[(get-else $ ?jel :journal-entry-line/account :account/unknown) ?account]
                                                  '[(get-else $ ?jel :journal-entry-line/debit 0.0) ?debit]
                                                  '[(get-else $ ?jel :journal-entry-line/credit 0.0) ?credit]
                                                  '[(get-else $ ?jel :journal-entry-line/location "") ?location]]
                                          }
                                  :args [(d/db (d/connect uri)) client-id]})
                                (sort-by first))]

    (reduce 
     (fn [acc bracket]
       (println (first all-ledger-entries))
       (assoc acc bracket (->> all-ledger-entries
                               (filter (fn [[d]]
                                         (<= (compare d bracket) 0)))
                               (reduce
                                (fn [acc [_ _ account location debit credit]]
                                  (-> acc
                                      (update-in [[location account] :debit] (fnil + 0.0) debit)
                                      (update-in [[location account] :credit] (fnil + 0.0) credit)
                                      (update-in [[location account] :count] (fnil + 0) 1))
                                  )
                                {})
                               (reduce-kv
                                (fn [acc [location account] {:keys [debit credit count]}]
                                  (let [account-type (account->type account)]
                                    (conj acc {:name (if-not (= "A" location)
                                                       (str (account->name account) "-" location)
                                                       (account->name account))
                                               :id (str account "-" location)
                                               :numeric_code (account->numeric-code account)
                                               :location (or location "")
                                               :amount (if account-type (if (#{:account-type/asset
                                                                               :account-type/dividend
                                                                               :account-type/expense} account-type)
                                                                          (- debit credit)
                                                                          (- credit debit) 
                                                                          )
                                                           0.0)
                                               :account_type account-type}))
                                  )

                                []))))
     {}
     brackets))
  )

;; 9804

new-results
old-results
(for [[k1 a1] (by :id (map #(dissoc % :location :account_type ) (filter :numeric_code new-results)))
      :let [a2 (get (by :id (map #(dissoc % :location :account_type ) (filter :numeric_code old-results)))
                         k1)]

      :when (not= a1 a2)]

  [a1 a2]
  )

(clojure.data/diff (set new-results) (set old-results))

;;16275




#_(d/query 
 {:query {:find ['?account '?location '?debit '?credit ]
          :in ['$]
          :where ['[?e :journal-entry/client 17592186046483]
                  '[?e :journal-entry/date ?d]
                  '[(<= ?d #inst "2020-09-01")]
                  '[?e :journal-entry/line-items ?jel]
                  '[(get-else $ ?jel :journal-entry-line/account :account/unknown) ?account]
                  '[(get-else $ ?jel :journal-entry-line/debit 0.0) ?debit]
                  '[(get-else $ ?jel :journal-entry-line/credit 0.0) ?credit]
                  '[(get-else $ ?jel :journal-entry-line/location "") ?location]]
          }
  :args [(d/db (d/connect uri))]})
