(ns auto-ap.views.pages.checks
  (:require [re-frame.core :as re-frame]
            [auto-ap.entities.clients :as client]
            [auto-ap.entities.vendors :as vendor]
            [auto-ap.entities.invoice :as invoice]
            [reagent.core :as reagent]
            [goog.string :as gstring]
            [clojure.spec.alpha :as s]
            [auto-ap.views.components.sorter :refer [sorted-column]]
            [auto-ap.views.components.vendor-filter :refer [vendor-filter]]
            [auto-ap.views.components.layouts :refer [side-bar-layout]]
            [auto-ap.views.components.typeahead :refer [typeahead]]
            [auto-ap.views.components.paginator :refer [paginator]]
            [auto-ap.events :as events]
            [auto-ap.views.utils :refer [dispatch-event date->str bind-field]]
            [auto-ap.utils :refer [by]]
            [auto-ap.views.pages.check :as check]
            [auto-ap.views.components.invoice-table :refer [invoice-table] :as invoice-table]
            [auto-ap.subs :as subs]))




(re-frame/reg-sub
 ::payment-page
 (fn [db]
   (-> db ::payment-page)))

(re-frame/reg-sub
 ::params
 (fn [db]
   (-> db (::params {}))))

(re-frame/reg-event-fx
 ::params-change
 (fn [cofx [_ params]]
   
   {:db (-> (:db cofx)
            (assoc-in [:status :loading] true)
            (assoc-in [::params] params))
    :graphql {:token (-> cofx :db :user)
              :query-obj {:venia/queries [[:payment_page
                                           (assoc params :client-id (:id @(re-frame/subscribe [::subs/client]))) 
                                           [[:payments [:id :status :amount :type :check_number :s3_url :date [:vendor [:name :id]] [:client [:name :id]]]]
                                            :total
                                            :start
                                            :end]]]} 
              :on-success [::received]}}))

(re-frame/reg-event-fx
 ::void-check
 (fn [{:keys [db]} [_ payment]]
   {:graphql
    {:token (-> db :user)
     :query-obj {:venia/operation {:operation/type :mutation
                                   :operation/name "VoidPayment"}
                 
                 :venia/queries [{:query/data [:void-payment
                                               {:payment-id (:id payment)}
                                               [:id :status :amount :check_number :s3_url :date [:vendor [:name :id]] [:client [:name :id]]]]}]}  
     :on-success [::payment-voided]}}))

(re-frame/reg-event-db
 ::payment-voided
 (fn [db [_ {:keys [void-payment]}]]
   (-> db
       (update-in [::payment-page :payments] (fn [payments]
                                    (mapv (fn [c]
                                            (if (= (:id c) (:id void-payment))
                                              (assoc void-payment :class "live-removed")
                                              c))
                                          payments))))))

(re-frame/reg-event-db
 ::received
 (fn [db [_ data]]
   (-> db
       (assoc ::payment-page (first (:payment-page data)))
       (assoc-in [:status :loading] false))))

(re-frame/reg-event-fx
 ::invalidated
 (fn [cofx [_ params]]
   {:dispatch [::params-change @(re-frame/subscribe [::params])]}))

(re-frame/reg-event-db
 ::change-selected-vendor
 (fn [db [_ key value]]
   (let [[key] key 
         updated (assoc-in db [::payment-page :vendor-filter key] value)]
     (if (and (= key :vendor-id)
              (not= value (get-in db [::params :vendor-id])))
       (do
         (re-frame/dispatch [::params-change (assoc (::params updated) :vendor-id value)])
         (assoc-in updated [::params :vendor-id] value))
       updated))))

(defn check-table [{:keys [id payment-page status on-params-change vendors params check-boxes checked on-check-changed expense-event]}]
  (let [#_#_state (reagent/atom (or @params {}))
        selected-client @(re-frame/subscribe [::subs/client])
        opc (fn [p]
              
              (on-params-change (merge @params p)))]
    (fn [{:keys [id payment-page status on-params-change vendors checked]}]
      (let [{:keys [sort-by asc]} @params
            {:keys [payments start end count total]} @payment-page
            selected-client @(re-frame/subscribe [::subs/client])
            percentage-size (if selected-client "50%" "33%")]
        [:div
         [paginator {:start start :end end :count count :total total
                     :on-change (fn [p ]
                                  (on-params-change (merge @params p)))}]
         "Showing " (inc start) "-" end "/" total
         
         [:table.table.is-fullwidth 
          [:thead  
           [:tr  
            
            
            (when-not selected-client
              [sorted-column {:on-sort opc
                              :style {:width percentage-size :cursor "pointer"}
                              :sort-key "client"
                              :sort-by sort-by
                              :asc asc}
               "Client"])

            [sorted-column {:on-sort opc
                            :style {:width percentage-size :cursor "pointer"}
                            :sort-key "vendor"
                            :sort-by sort-by
                            :asc asc}
             "Vendor"]
            [sorted-column {:on-sort opc
                            :style {:width percentage-size :cursor "pointer"}
                            :sort-key "check-number"
                            :sort-by sort-by
                            :asc asc}
             "Check #"]
            [sorted-column {:on-sort opc
                            :style {:width "8em" :cursor "pointer"}
                            :sort-key "date"
                            :sort-by sort-by
                            :asc asc}
             "Date"]
            [sorted-column {:on-sort opc
                            :style {:width "8em" :cursor "pointer"}
                            :sort-key "amount"
                            :sort-by sort-by
                            :asc asc}
             "Amount"]

            [sorted-column {:on-sort opc
                            :style {:width "8em" :cursor "pointer"}
                            :sort-key "status"
                            :sort-by sort-by
                            :asc asc}
             "Status"]
            
            
            [:th {:style {:width "10em"}} "" ]]]
          [:tbody
           (if (:loading @status)
             [:tr 
              [:td {:col-span 5}
               [:i.fa.fa-spin.fa-spinner]]]
             (for [{:keys [client s3-url payments type check-number date amount id vendor status] :as i} (:payments @payment-page)]
               ^{:key id}
               [:tr {:class (:class i)}
                
                (when-not selected-client
                  [:td (:name client)])
                [:td (:name vendor)]
                [:td (cond
                       (= :cash type) "Cash"
                       (= :debit type) "Debit"
                       :else check-number)]
                [:td (date->str date) ]
                [:td (gstring/format "$%.2f" amount )]
                [:td status]
                [:td
                 (when (or (= :pending status)
                           (and (#{":cash" ":debit" :cash :debit} type)
                                (not= :voided status)))
                   [:button.button.is-warning.is-outlined {:on-click (dispatch-event [::void-check i])} [:span [:span.icon [:i.fa.fa-minus-circle]]]])
                 (if s3-url
                   [:a.tag {:href s3-url :target "_new"} [:i.fa.fa-money-check] [:span.icon [:i.fa.fa-money]] (str  " " check-number " (" (gstring/format "$%.2f" amount ) ")")]
                   [:span.tag [:i.fa.fa-money-check] [:span.icon [:i.fa.fa-money]] (str  " " check-number " (" (gstring/format "$%.2f" amount ) ")")])
                 ]
                ]))]]]))))


(def checks-content
  (with-meta
    (fn []
      (let [current-client @(re-frame/subscribe [::subs/client])]
        [:div 
         [:h1.title "Checks"]
         [check-table {:id :payments
                       :params (re-frame/subscribe [::params])
                       :payment-page (re-frame/subscribe [::payment-page])
                       :status (re-frame/subscribe [::subs/status])
                       :on-params-change (fn [params]
                                           (re-frame/dispatch [::params-change params]))}]]))
    {:component-will-mount #(re-frame/dispatch-sync [::params-change {}]) }))



(defn checks-page []
  [side-bar-layout {:side-bar
                    [:div 
                    [:p.menu-label "Vendor"]
                     [:div [vendor-filter {:on-change-event [::change-selected-vendor]
                                           :value (:vendor-filter @(re-frame/subscribe [::payment-page]))
                                           :vendors @(re-frame/subscribe [::subs/vendors])}]]]
                    :main [checks-content]}])
