(ns auto-ap.intuit.import
  (:require [amazonica.aws.s3 :as s3]
            [auto-ap.datomic :refer [conn remove-nils]]
            [auto-ap.intuit.core :as i]
            [auto-ap.utils :refer [by]]
            [auto-ap.yodlee.import :as y]
            [clj-time.coerce :as coerce]
            [clj-time.core :as time]
            [clj-time.format :as f]
            [clojure.string :as str]
            [clojure.tools.logging :as log]
            [datomic.api :as d]
            [mount.core :as mount]
            [unilog.context :as lc]
            [yang.scheduler :as scheduler]))

(defn get-intuit-bank-accounts [db]
  (-> (d/q '[:find ?ba ?external-id
             :in $
             :where [?ba :bank-account/intuit-bank-account ?iab]
             [?iab :intuit-bank-account/external-id ?external-id]]
           db)))

(defn upsert-transactions []
  (let [db (d/db conn)
        import-id (y/start-import :import-source/intuit "Automated Intuit User")
        stats (atom {:import-batch/imported 0
                     :import-batch/extant 0
                     :import-batch/suppressed 0})]

    (doseq [[bank-account external-id] (get-intuit-bank-accounts db)
            :let [bank-account (d/entity db bank-account)
                  end (auto-ap.time/local-now)
                  start (time/plus end (time/days -30))]]
      (log/infof "importing from %s to %s for %s" start end external-id)
      (let [transactions (->> (i/get-transactions (auto-ap.time/unparse start auto-ap.time/iso-date)
                                                  (auto-ap.time/unparse end auto-ap.time/iso-date)
                                                  external-id)
                              (mapv (fn [r]
                                      {:client-id (:db/id (:client/_bank-accounts bank-account))
                                       :bank-account-id (:db/id bank-account)
                                       :description-original (:Memo/Description r)
                                       :amount (Double/parseDouble (:Amount r))
                                       :date (auto-ap.time/parse (:Date r) auto-ap.time/iso-date)
                                       :status "posted"})))]
        (log/infof "%d transactions found" (count transactions))
        (let [result (y/grouped-import transactions import-id)]
          (swap! stats
                 (fn [s]
                   (merge-with + s {:import-batch/imported  (count (:import result))
                                    :import-batch/extant (count (:extant result))
                                    :import-batch/suppressed (count (:suppressed result))}))))))
    (y/finish-import (assoc @stats :db/id import-id))))


(defn dry-run-upsert-transactions []
  (let [db (d/db conn)]
    (clojure.data.csv/write-csv
     *out*
     (->> 
      (for [[bank-account external-id]  (get-intuit-bank-accounts db)
            :let [bank-account (d/entity db bank-account)
                  end (auto-ap.time/local-now)
                  start (time/plus end (time/days -30))]
            r (i/get-transactions (auto-ap.time/unparse start auto-ap.time/iso-date)
                                  (auto-ap.time/unparse end auto-ap.time/iso-date)
                                  external-id)]
        {:client-id (:db/id (:client/_bank-accounts bank-account))
         :client-code (:client/code (:client/_bank-accounts bank-account))
         :bank-account-id (:db/id bank-account)
         :bank-account-code (:bank-account/code bank-account)
         :external-id external-id
         :description-original (:Memo/Description r)
         :amount (Double/parseDouble (:Amount r))
         :date (auto-ap.time/parse (:Date r) auto-ap.time/iso-date)
         :status "posted"})
      (y/grouped-new)
      (map (juxt :client-code :bank-account-code :external-id :description-original :amount #(auto-ap.time/unparse-local (:date %) auto-ap.time/normal-date) :new?)))
     :separator \tab)))


(defn upsert-accounts []
  (let [token (i/get-fresh-access-token)
        bank-accounts (i/get-bank-accounts token)]
    @(d/transact conn (mapv
                      (fn [ba]
                        {:intuit-bank-account/external-id (:name ba)
                         :intuit-bank-account/name (:name ba)})
                      bank-accounts))))
