;; This buffer is for Clojure experiments and evaluation.

;; Press C-j to evaluate the last expression.

;; You can also press C-u C-j to evaluate the expression and pretty-print its result.
(require '[auto-ap.utils :refer [dollars=]])

(defn get-bad-ones []
  

  (->> (->> (d/q '[:find ?c
                   :in $
                   :where [?c :client/code]]
                 (d/db auto-ap.datomic/conn))
            (map first))
       (mapcat #(->> (d/query {:query {:find ['?je '?a '(sum ?debit) '(sum ?credit)]
                                       :with ['?jel]
                                       :in '[$ ?c]
                                       :where ['[?je :journal-entry/client ?c]
                                               '[?je :journal-entry/amount ?a]
                                               '[?je :journal-entry/line-items ?jel]
                                               '[(get-else $ ?jel :journal-entry-line/debit 0.0) ?debit]
                                               '[(get-else $ ?jel :journal-entry-line/credit 0.0) ?credit]]
                                       }
                               :args [(d/db auto-ap.datomic/conn) %]})
                     (filter (fn [[_ a d c]]
                               (or (not (dollars= a d))
                                   (not (dollars= a c)))))))
       
       #_(count)
       #_(take 3)))

(def bad-ones (get-bad-ones))

(count bad-ones)

(defn bad-invoices [bad-ones]
  (->> bad-ones
       
       (map first)
       (map (fn [je]
              (:journal-entry/original-entity (d/entity (d/db auto-ap.datomic/conn)
                                                        je))))
       (filter (fn [invoice?]
                 (:invoice/total invoice?)))
       #_(map (fn [invoice]
              {:total (:invoice/total invoice)
               :client-code (:client/code (:invoice/client invoice))
               :invoice-number (:invoice/invoice-number invoice)
               :vendor (:vendor/name (:invoice/vendor invoice))
               :accounts (map
                          (fn [ea]
                            (str (:account/numeric-code (:invoice-expense-account/account ea)) ": " (:invoice-expense-account/amount ea)))
                          (:invoice/expense-accounts invoice))}))
       ))

(get-schema "invoice-expense-account")

(defn bad-invoices-with-zero-expense-accounts [bad-ones]
  (->> bad-ones
       
       (map first)
       (map (fn [je]
              (:journal-entry/original-entity (d/entity (d/db auto-ap.datomic/conn)
                                                        je))))
       (filter (fn [invoice?]
                 (and (:invoice/total invoice?)
                      (= 0 (count (:invoice/expense-accounts invoice?))))))
       (map (fn [invoice]
              {:db/id (:db/id invoice)
               :invoice/expense-accounts [{:invoice-expense-account/amount (:invoice/total invoice)
                                           :invoice-expense-account/location (first (:client/locations (:invoice/client invoice)))
                                           :invoice-expense-account/account (-> invoice
                                                                                :invoice/vendor
                                                                                (auto-ap.datomic.vendors/account-for-client-id (:db/id (:invoice/client invoice)))
                                                                                :db/id)}
                                          ]}
              ))

       #_(map (fn [invoice]
                {:total (:invoice/total invoice)
                 :client-code (:client/code (:invoice/client invoice))
                 :invoice-number (:invoice/invoice-number invoice)
                 :vendor (:vendor/name (:invoice/vendor invoice))
                 :accounts (map
                            (fn [ea]
                              (str (:account/numeric-code (:invoice-expense-account/account ea)) ": " (:invoice-expense-account/amount ea)))
                            (:invoice/expense-accounts invoice))}))
       ))

@(d/transact auto-ap.datomic/conn (bad-invoices-with-zero-expense-accounts bad-ones))

(defn bad-transactions [bad-ones]
  (->> bad-ones
       
       (map first)
       (map (fn [je]
              (:journal-entry/original-entity (d/entity (d/db auto-ap.datomic/conn)
                                                        je))))
       (filter (fn [invoice?]
                 (:transaction/amount invoice?)))
       
       ))

(doseq [i (bad-invoices bad-ones)]
  (println "touching invoice " i)
  (auto-ap.ledger/touch-invoice (:db/id i)))

(doseq [i (bad-transactions bad-ones)]
  (println "touching tx " i)
  (auto-ap.ledger/touch-transaction (:db/id i)))

(clojure.pprint/pprint (bad-invoices (get-bad-ones)))
(count (bad-transactions (get-bad-ones)))


(defn get-bad-transactions2 []
  (->> (d/query {:query {:find ['?tx '?a '(sum ?a2)]
                         :with ['?acc]
                         :in '[$]
                         :where ['[?tx :transaction/amount ?a]
                                 '[?tx :transaction/accounts ?acc]
                                 '[(get-else $ ?acc :transaction-account/amount 0.0) ?a2]]
                         }
                 :args [(d/db auto-ap.datomic/conn)]})
       (filter (fn [[_ a d ]]
                 (not (dollars= (Math/abs a) (Math/abs d)))))
       #_(count)
       #_(take 3)))

(clojure.pprint/pprint (count (get-bad-transactions2)))

()
