(ns auto-ap.datomic.clients
  (:require
   [auto-ap.datomic :refer [conn]]
   [auto-ap.search :as search]
   [clj-time.coerce :as coerce]
   [clojure.string :as str]
   [datomic.client.api :as dc]))

(defn cleanse [e]
  (-> e
      (assoc :client/yodlee-provider-accounts (get e :yodlee-provider-account/_client))
      (assoc :client/plaid-items (get e :plaid-item/_client))
      (update :client/locked-until #(some-> % coerce/to-date-time))
      (update-in [:client/square-integration-status :integration-status/state] :db/ident)
      (update-in [:client/square-integration-status :integration-status/last-attempt] #(some-> % coerce/to-date-time))
      (update-in [:client/square-integration-status :integration-status/last-updated] #(some-> % coerce/to-date-time))
      (update :client/location-matches
              (fn [lms]
                (map #(assoc % :location-match/match (first (:location-match/matches %))) lms)))
      (update :client/bank-accounts
              (fn [bas]
                (map (fn [i ba]
                       (-> ba
                           (update :bank-account/type :db/ident )
                           (update-in [:bank-account/integration-status :integration-status/state] :db/ident)
                           (update-in [:bank-account/integration-status :integration-status/last-attempt] #(some-> % coerce/to-date-time))
                           (update-in [:bank-account/integration-status :integration-status/last-updated] #(some-> % coerce/to-date-time))
                           (update :bank-account/start-date #(some-> % (coerce/to-date-time)))
                           (update :bank-account/sort-order (fn [so] (or so i)))))
                     (range) bas)))))
(defn get-all []
  (->> (dc/q '[:find (pull ?e [*
                              {:client/square-integration-status [:integration-status/message
                                                                  :integration-status/last-attempt
                                                                  :integration-status/last-updated
                                                                  :db/id
                                                                  {:integration-status/state [:db/ident]}]}
                              {:client/address [*]}
                              {:client/square-locations [:square-location/square-id
                                                         :square-location/name
                                                         :square-location/client-location
                                                         :db/id]}

                              {:client/ezcater-locations [{:ezcater-location/caterer [:ezcater-caterer/name :db/id]}
                                                          :ezcater-location/location
                                                          :db/id]}
                              {:client/bank-accounts [* {:bank-account/type [*]
                                                         :bank-account/yodlee-account [:yodlee-account/name :yodlee-account/id :yodlee-account/number]
                                                         :bank-account/plaid-account [:plaid-account/name :db/id :plaid-account/number :plaid-account/balance]
                                                         :bank-account/intuit-bank-account [:intuit-bank-account/name :intuit-bank-account/external-id :db/id]
                                                         :bank-account/integration-status [:integration-status/message
                                                                                           :db/id
                                                                                           :integration-status/last-attempt
                                                                                           :integration-status/last-updated
                                                                                           {:integration-status/state [:db/ident]}]}
                                                      ]}
                              {:yodlee-provider-account/_client [*]}
                              {:plaid-item/_client [*]}
                              {:client/emails [:db/id :email-contact/email :email-contact/description]}])
              :where [?e :client/name]]
            (dc/db conn))
       (map first)
       (map cleanse)))

(defn get-by-id [id]
  (->> 
   (dc/pull (dc/db conn ) 
           '[* {:client/bank-accounts [* {:bank-account/type                [*]
                                          :bank-account/yodlee-account      [:yodlee-account/name :yodlee-account/id :yodlee-account/number]
                                          :bank-account/intuit-bank-account [:intuit-bank-account/name :intuit-bank-account/external-id :db/id]
                                          :bank-account/plaid-account       [:plaid-account/name :db/id :plaid-account/number :plaid-account/balance]}]
                :client/emails        [:db/id :email-contact/email :email-contact/description]}
             {:client/ezcater-locations [{:ezcater-location/caterer [:ezcater-caterer/name :db/id]}
                                         :ezcater-location/location
                                         :db/id]}
             {:yodlee-provider-account/_client [*]}
             {:plaid-item/_client [*]}]
         id)
   (cleanse)))

(defn code->id [code]
  (->> 
   (dc/q (-> {:query {:find ['?e]
                         :in ['$ '?code]
                         :where [['?e :client/code '?code ]]}
                 :args [(dc/db conn) code]}))
   (first)
   (first)))

(defn best-match [identifier]
  (first (search/search-ids {:q (str/replace identifier #"[\(\)\-/\*\]\[\#:\&]" " ")} "client")))

(defn exact-match [identifier]
  (first (search/search-ids {:exact-match (str/upper-case identifier)} "client")))

(defn rebuild-search-index []
  (search/full-index-query  
    (for [result (map first (dc/q '[:find (pull ?v [:client/name :client/matches :db/id])
                                       :in $
                                       :where [?v :client/code]]
                                     (dc/db conn)))
          match  (conj (or (:client/matches result) [])
                      (:client/name result))]
      {:id   (:db/id result)
       :text match
       :exact-match (str/upper-case match)})
    "client"))
