(ns auto-ap.import.manual
  (:require
   [auto-ap.datomic :refer [conn]]
   [auto-ap.import.manual.common :as c]
   [auto-ap.import.transactions :as t]
   [clj-time.coerce :as coerce]
   [clojure.data.csv :as csv]
   [datomic.api :as dc]))



(def columns [:status :raw-date :description-original :high-level-category nil nil :amount nil nil nil nil nil :bank-account-code :client-code])

(defn tabulate-data [data]
  (->>
   (csv/read-csv data :separator \tab)
   (drop 1)
   (map (fn [row]
          (into {} (->> (map vector columns row)
                        (filter (fn [[k _]] k))))))))

(defn manual->transaction [{:keys [description-original bank-account-code] :as transaction} bank-account-lookup client-lookup]
  (-> {:transaction/description-original description-original
       :transaction/status "POSTED"}
      (c/assoc-or-error :transaction/client #(if-let [client-id (client-lookup bank-account-code)]
                                               client-id
                                               (throw (Exception. (str "Cannot find client for bank account code " bank-account-code)))))
      (c/assoc-or-error :transaction/bank-account #(if-let [bank-account-id (bank-account-lookup bank-account-code)]
                                                     bank-account-id
                                                     (throw (Exception. (str "Cannot find bank account by code " bank-account-code)))))
      (c/assoc-or-error :transaction/date #(coerce/to-date (c/parse-date transaction)))
      (c/assoc-or-error :transaction/amount #(c/parse-amount transaction))))

(defn import-batch [transactions user]
  (let [bank-account-code->client       (into {}
                                        (dc/q '[:find ?bac ?c
                                                :in $
                                                :where
                                                [?c :client/bank-accounts ?ba]
                                                [?ba :bank-account/code ?bac]]
                                              (dc/db conn)))
        bank-account-code->bank-account (into {}
                                              (dc/q '[:find ?bac ?ba
                                                      :in $
                                                      :where [?ba :bank-account/code ?bac]]
                                                    (dc/db conn)))
        import-batch                    (t/start-import-batch :import-source/manual user)
        transactions                    (->> transactions
                          (map (fn [t]
                                 (manual->transaction t bank-account-code->bank-account bank-account-code->client)))
                          (t/apply-synthetic-ids ))]
    (try
      (doseq [transaction transactions]
        (when-not (seq (:errors transaction))
          (t/import-transaction! import-batch transaction)))

      (t/finish! import-batch)
      (assoc (t/get-stats import-batch)
             :failed-validation (count (filter :errors transactions))
             :sample-error (first (first (map :errors (filter :errors transactions)))))
      (catch Exception e
        (t/fail! import-batch e)
        (t/get-stats import-batch)))))
