(ns auto-ap.import.plaid
  (:require
   [auto-ap.datomic :refer [conn]]
   [auto-ap.import.common :refer [wrap-integration]]
   [auto-ap.import.transactions :as t]
   [auto-ap.plaid.core :as p]
   [auto-ap.time :as atime]
   [auto-ap.utils :refer [allow-once by]]
   [clj-time.coerce :as coerce]
   [clj-time.core :as time]
   [datomic.client.api :as dc]
   [digest :as di]
   [unilog.context :as lc]))

(defn get-plaid-accounts [db]
  (-> (dc/q '[:find ?ba ?c ?external-id ?t 
             :in $ 
             :where
             [?c :client/bank-accounts ?ba]
             [?ba :bank-account/plaid-account ?pa]
             [?pa :plaid-account/external-id ?external-id]
             [?pi :plaid-item/accounts ?pa]
             [?pi :plaid-item/access-token ?t]]
           db )))


(defn plaid->transaction [t]
  #:transaction {:description-original (:name t)
                 :raw-id (:transaction_id t)
                 :id #_{:clj-kondo/ignore [:unresolved-var]}
                     (di/sha-256 (:transaction_id t))
                 :amount (if (= "credit" (:type (:account t)))
                           (- (double (:amount t)))
                           (double (:amount t)))
                 :date (coerce/to-date (atime/parse (:authorized_date t) atime/iso-date))
                 :status "POSTED"})


(defn import-plaid-int []
  (lc/with-context {:source "Import plaid transactions"}
    (let [import-batch (t/start-import-batch :import-source/plaid "Automated plaid user")
          end (atime/local-now)
          start (time/plus end (time/days -30))]
      (try
        (doseq [[bank-account-id client-id external-id access-token] (get-plaid-accounts (dc/db conn))
                :let [transaction-result (wrap-integration #(p/get-transactions access-token external-id start end)
                                                           bank-account-id)
                      accounts-by-id (by  :account_id (:accounts transaction-result))]
                transaction (:transactions transaction-result)]
          (when (not (:pending transaction))
            (t/import-transaction! import-batch (assoc (plaid->transaction (assoc transaction
                                                                                   :account
                                                                                   (accounts-by-id (:account_id transaction))))
                                                     :transaction/bank-account bank-account-id
                                                     :transaction/client client-id))))
        (t/finish! import-batch)
        (catch Exception e
          (t/fail! import-batch e))))))

(def import-plaid (allow-once import-plaid-int))

