(ns iol-ion.integration.tx
  (:require
   [auto-ap.datomic :refer [conn]]
   [auto-ap.integration.util
    :refer [apply-tx setup-test-data test-invoice test-transaction wrap-setup]]
   [clojure.test :as t :refer [deftest is testing use-fixtures]]
   [datomic.api :as dc]
   [iol-ion.tx.upsert-invoice :as sut-i]
   [iol-ion.tx.upsert-transaction :as sut-t]))

(use-fixtures :each wrap-setup)

(def journal-pull [:journal-entry/date
                   :journal-entry/original-entity
                   :journal-entry/client
                   :journal-entry/source
                   :journal-entry/cleared
                   :journal-entry/amount
                   :journal-entry/vendor
                   {:journal-entry/line-items [{:journal-entry-line/account '[:account/name]}
                                               :journal-entry-line/location
                                               :journal-entry-line/credit
                                               :journal-entry-line/dirty
                                               :journal-entry-line/debit]}])


(deftest upsert-invoice
  (testing "Importing should create a journal entry"
    (let [{:strs [invoice-id
                  test-client-id
                  test-vendor-id
                  ]} (setup-test-data
                                 [(test-invoice :db/id "invoice-id"
                                                :invoice/import-status :import-status/pending
                                                :invoice/total 200.0
                                                )])]
      
      (is (nil? (:db/id (dc/pull (dc/db conn) journal-pull
                                 [:journal-entry/original-entity invoice-id]))))
      (let [db-after   (apply-tx (sut-i/upsert-invoice
                                   (dc/db conn)
                                   {:db/id                 invoice-id
                                    :invoice/import-status :import-status/imported}))]
        
        (is (= #:journal-entry{:date            #inst "2022-01-01T00:00:00.000-00:00",
                        :original-entity #:db{:id invoice-id},
                        :client          #:db{:id test-client-id},
                        :line-items
                        [#:journal-entry-line{:account
                                              #:account{:name
                                                        "Accounts Payable"},
                                              :credit   200.0,
                                              :location "A",
                                              :dirty    true}
                         #:journal-entry-line{:account
                                              #:account{:name "Account"},
                                              :location "DT",
                                              :dirty    true,
                                              :debit    100.0}],
                        :source          "invoice",
                        :cleared         false,
                        :amount          200.0,
                        :vendor          #:db{:id test-vendor-id}} 
               (dc/pull db-after journal-pull
                        [:journal-entry/original-entity invoice-id])))

        (testing "voiding an invoice should remove the journal entry"
          (let [db-after (apply-tx (sut-i/upsert-invoice
                                       (dc/db conn)
                                       {:db/id                 invoice-id
                                        :invoice/status :invoice-status/voided}))]
            
            (is (= nil 
                   (dc/pull db-after journal-pull
                            [:journal-entry/original-entity invoice-id])))))
        (testing "invoice should remove the journal entry"
          (let [db-after (apply-tx (sut-i/upsert-invoice
                                     (dc/db conn)
                                     {:db/id          invoice-id
                                      :invoice/status :invoice-status/unpaid
                                      :invoice/import-status :import-status/pending}))]
            
            (is (= nil 
                   (dc/pull db-after journal-pull
                            [:journal-entry/original-entity invoice-id])))))))))

(deftest upsert-transaction []
  (testing "should upsert transaction"
    (let [{:strs [test-client-id
                  test-bank-account-id
                  test-account-id
                  test-vendor-id
                  test-transaction-id
                  test-import-batch-id
                  ]} (setup-test-data
                       [(test-transaction :db/id "test-transaction-id"
                                      )
                        {:db/id "test-import-batch-id"
                         :import-batch/date #inst "2022-01-01"}])
          update     (sut-t/upsert-transaction (dc/db conn) {:db/id test-transaction-id
                                                           :transaction/id           "hello"
                                                           :transaction/bank-account test-bank-account-id
                                                           :transaction/amount       500.00
                                                           :transaction/client       test-client-id
                                                           :transaction/date         #inst "2022-01-01"
                                                           :transaction/vendor       test-vendor-id
                                                           :transaction/approval-status :transaction-approval-status/approved
                                                           :transaction/accounts     [
                                                                                      {:db/id "account"
                                                                                       :transaction-account/account  test-account-id
                                                                                       :transaction-account/location "A"
                                                                                       :transaction-account/amount   500.00}]})]
      
      (is (nil? (:db/id (dc/pull (dc/db conn) journal-pull
                                 [:journal-entry/original-entity test-transaction-id]))))
      (let [db-after (apply-tx update)]
        (testing "should create journal entry"
          (is (= #:journal-entry{:date            #inst "2022-01-01T00:00:00.000-00:00",          
                                 :original-entity #:db{:id test-transaction-id},
                                 :client          #:db{:id test-client-id},
                                 :source          "transaction",
                                 :cleared         true,
                                 :amount          500.0,
                                 :vendor          #:db{:id test-vendor-id},
                                 :line-items
                                 [#:journal-entry-line{:location "A",
                                                       :dirty    true,
                                                       :debit    500.0}
                                  #:journal-entry-line{:account
                                                       #:account{:name "Account"},
                                                       :location "A",
                                                       :credit   500.0,
                                                       :dirty    true}]} 
                 (dc/pull db-after journal-pull
                          [:journal-entry/original-entity test-transaction-id])))))

      )))
