(ns auto-ap.graphql.clients
  (:require [auto-ap.datomic :refer [conn]]
            [auto-ap.logging :as alog]
            [auto-ap.datomic.clients :as d-clients]
            [auto-ap.graphql.utils
             :refer [->graphql <-graphql assert-admin attach-tracing-resolvers
                     can-see-client? is-admin? result->page]]
            [clj-time.coerce :as c]
            [clj-time.core :as time]
            [clojure.set :as set]
            [com.brunobonacci.mulog :as mu]
            [datomic.api :as dc]))

(defn get-client [context _ _]
  (->graphql
   (->> (d-clients/get-minimal)
        (filter #(can-see-client? (:id context) %)))))

(defn get-admin-client [context {:keys [id]} _]
  (assert-admin (:id context))
  (->graphql
    (-> (d-clients/get-by-id id)
         (update :client/bank-accounts (fn [bas]
                                           (map #(set/rename-keys % {:bank-account/use-date-instead-of-post-date? :use-date-instead-of-post-date}) bas))))))

(defn get-client-page [context args _]
  (assert-admin (:id context))
  (let [args                    (assoc args :id (:id context))
        [clients clients-count] (d-clients/get-graphql-page (assoc (<-graphql (:filters args))
                                                                   :clients (:clients context)))
        clients (->> clients
                     
                     (map (fn [c]
                            (update c :client/bank-accounts (fn [bas]
                                                              (map #(set/rename-keys % {:bank-account/use-date-instead-of-post-date? :use-date-instead-of-post-date}) bas)))))
                     (map (fn [c]
                            (if (is-admin? (:id context))
                              c
                              (-> c
                                  (dissoc :client/yodlee-provider-accounts)
                                  (dissoc :client/plaid-items)))))
                     (map (fn [c]
                            (update c :client/bank-accounts
                                    (fn [bank-accounts]
                                      (mapv (fn [ba]
                                              (assoc ba :bank-account/yodlee-balance-old nil))
                                            bank-accounts))))))]
    (result->page clients clients-count :clients (:filters args))))








(def objects
  {:location_match
   {:fields {:location {:type 'String}
             :match {:type 'String}
             :id {:type :id}}}

   :square_location
   {:fields {:client_location {:type 'String}
             :name            {:type 'String}
             :square_id       {:type 'String}
             :id              {:type :id}}}

   :ezcater_location
   {:fields {:location {:type 'String}
             :caterer         {:type :ezcater_caterer}
             :id              {:type :id}}}

   :email_contact {:fields {:id          {:type :id}
                            :email       {:type 'String}
                            :description {:type 'String}}}

   :client
   {:fields {:id {:type :id}
             :name {:type 'String}
             :locked_until {:type :iso_date}
             :code {:type 'String}
             :feature_flags {:type '(list String)}
             :groups {:type '(list String)}
             :square_auth_token {:type 'String}
             :signature_file {:type 'String}
             :square_integration_status {:type :integration_status}
             :week_a_debits {:type :money}
             :week_a_credits {:type :money}
             :week_b_debits {:type :money}
             :week_b_credits {:type :money}
             :email {:type 'String}
             :emails {:type '(list :email_contact)}
             :address {:type :address}
             :location_matches {:type '(list :location_match)}
             :locations {:type '(list String)}
             :matches {:type '(list String)}
             :bank_accounts {:type '(list :bank_account)}
             :square_locations {:type '(list :square_location)}
             :ezcater_locations {:type '(list :ezcater_location)}
             :forecasted_transactions {:type '(list :forecasted_transaction)}
             :yodlee_provider_accounts {:type '(list :yodlee_provider_account)}
             :plaid_items {:type '(list :plaid_item)}}}

   :client_page 
   {:fields {:clients {:type '(list :client)}
             :count   {:type 'Int}
             :total   {:type 'Int}
             :start   {:type 'Int}
             :end     {:type 'Int}}}

   

   :bank_account
   {:fields {:id {:type :id}
             :integration_status {:type :integration_status}
             :type {:type :ident}
             :start_date {:type :iso_date}
             :number {:type 'String}
             :numeric_code {:type 'Int}
             :sort_order {:type 'Int}
             :visible {:type 'Boolean}
             :include_in_reports {:type 'Boolean}
             :routing {:type 'String}
             :code {:type 'String}
             :check_number {:type 'Int}
             :name {:type 'String}
             :bank_code {:type 'String}
             :bank_name {:type 'String}
             :current_balance {:type :money}
             :yodlee_balance_old {:type :money}
             :yodlee_account_id {:type 'Int}
             :yodlee_account {:type :yodlee_account}
             :plaid_account {:type :plaid_account}
             :intuit_bank_account {:type :intuit_bank_account}
             :use_date_instead_of_post_date {:type 'Boolean}
             :locations {:type '(list String)}}}

   :forecasted_transaction {:fields {:identifier {:type 'String}
                                     :id {:type :id}
                                     :day_of_month {:type 'Int}
                                     :amount {:type :money}}}

})

(def queries
  {:client {:type '(list :client)
            :resolve :get-client}

   :admin_client {:type    :client
                  :args {:id {:type :id}}
                  :resolve :get-admin-client}
   :client_page {:type    :client_page
                 :args {:filters {:type :client_filters}}
                 :resolve :get-client-page}})

(def mutations
  {})

(def input-objects
  { :client_filters
   {:fields {:code {:type 'String}
             :name_like {:type 'String}
             :start    {:type 'Int}
             :per_page {:type 'Int}
             :sort     {:type '(list :sort_item)}}} })

(def enums
  {:bank_account_type {:values [{:enum-value :check}
                                {:enum-value :credit}
                                {:enum-value :cash}]}})

(def resolvers
  {:get-client get-client
   :get-admin-client get-admin-client
   :get-client-page get-client-page })


(defn attach [schema]
  (-> 
   (merge-with merge schema
               {:objects objects
                :queries queries
                :mutations mutations
                :input-objects input-objects
                :enums enums})
   (attach-tracing-resolvers resolvers)))
