(ns auto-ap.views.pages.unpaid-invoices
  (:require [re-frame.core :as re-frame]
            [reagent.core :as r]
            [clojure.string :as str]
            [clojure.spec.alpha :as s]
            [cljs-time.core :as c]
            [goog.string :as gstring]
            [auto-ap.entities.clients :as client]
            [auto-ap.entities.invoice :as invoice]
            [auto-ap.entities.vendors :as vendor]
            [bidi.bidi :as bidi]
            [auto-ap.views.components.layouts :refer [side-bar-layout]]
            [auto-ap.routes :as routes]
            [auto-ap.views.components.expense-accounts-dialog :as expense-accounts-dialog]
            [auto-ap.views.components.vendor-dialog :refer [vendor-dialog]]
            [auto-ap.views.components.vendor-filter :refer [vendor-filter]]
            [auto-ap.views.components.invoices.side-bar :refer [invoices-side-bar]]
            [auto-ap.expense-accounts :as expense-accounts]
            [auto-ap.entities.invoices-expense-accounts :as invoices-expense-accounts]
            [auto-ap.views.utils :refer [active-when dispatch-event bind-field horizontal-field date->str date-time->str str->date pretty standard]]
            [auto-ap.utils :refer [by replace-if]]
            [auto-ap.views.pages.check :as check]
            [auto-ap.views.components.invoice-table :refer [invoice-table] :as invoice-table]
            [auto-ap.views.components.modal :refer [modal action-modal]]
            [auto-ap.views.components.expense-accounts-dialog :refer [change-expense-accounts-modal ] :as change-expense-accounts]
            [auto-ap.views.components.typeahead :refer [typeahead]]
            [auto-ap.subs :as subs]
            [auto-ap.events :as events]))
(def invoice-read [:id :total :outstanding-balance :date :invoice-number :status
                   [:client [:id :name :locations]]
                   [:payments [:amount [:payment [:amount :s3_url :check_number ]]]]
                   [:vendor [:id :name]]
                   [:expense_accounts [:amount :id :expense_account_id
                                       :location
                                       [:expense_account [:id :name [:parent [:id :name]]]]]]])
(re-frame/reg-sub
 ::invoice-page
 (fn [db]
   (-> db ::invoice-page)))

(re-frame/reg-sub
 ::invoice
 (fn [db id]
   (get (by :id (-> db ::invoice-page :invoices )) id)))

(re-frame/reg-sub
 ::advanced-print-checks
 (fn [db]
   (-> db ::advanced-print-checks)))

(re-frame/reg-sub
 ::handwrite-checks
 (fn [db]
   (-> db ::handwrite-checks)))

(re-frame/reg-sub
 ::change-expense-accounts
 (fn [db]
   (-> db ::change-expense-accounts)))

(re-frame/reg-sub
 ::check-results
 (fn [db]
   (-> db ::check-results)))

(re-frame/reg-sub
 ::new-invoice
 (fn [db]
   (-> db ::new-invoice)))

(re-frame/reg-sub
 ::edit-invoice
 (fn [db]
   (-> db ::edit-invoice)))

(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 (invoice-table/query (-> params (assoc :import-status "imported") (dissoc :invoice-number-like-current)) ) 
              :on-success [::received]}}))
(re-frame/reg-event-db
 ::unmount-invoices
 (fn [db [_ data]]
   (-> db
       (dissoc ::invoice-page ))))

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

(re-frame/reg-event-db
 ::toggle-check
 (fn [db [_ id invoice]]
   (-> db
       (update-in [::invoice-page :checked] (fn [x]
                                                 (let [x (or x {})]
                                                   (if (x id)
                                                     (dissoc x id)
                                                     (assoc x id invoice))))))))

(re-frame/reg-event-db
 ::print-checks-clicked
 (fn [db _]
   (update-in db [::invoice-page :print-checks-shown?] #(not %) )))

(re-frame/reg-event-db
 ::advanced-print-checks
 (fn [db _]
   (let [{:keys [checked invoices]} (get-in db [::invoice-page])]
     (-> db
         (update-in [::invoice-page :print-checks-shown?] #(not %) )
         (assoc-in [::advanced-print-checks] {:shown? true
                                              :bank-account-id (:id (first (:bank-accounts @(re-frame/subscribe [::subs/clients]))))
                                              :invoices (->> checked
                                                             vals
                                                             (map #(assoc % :amount (:outstanding-balance %))))} )))))

(re-frame/reg-event-fx
 ::handwrite-checks
 (fn [{:keys [db]} _]
   (let [{:keys [checked invoices]} (get-in db [::invoice-page])
         invoice (->> invoices
                      (filter (comp checked :id))
                      first)
         ]
     
     {:dispatch [::events/modal-status ::handwrite-checks {:visible? true}]
      :db (-> db
              (update-in [::invoice-page :print-checks-shown?] #(not %) )
              (assoc-in [::handwrite-checks] {:bank-account-id (:id (first (:bank-accounts @(re-frame/subscribe [::subs/client]))))
                                              :amount (:outstanding-balance invoice)
                                              :invoice invoice } ))})))

(re-frame/reg-event-db
 ::cancel-advanced-print
 (fn [db _]
   (assoc-in db [::advanced-print-checks :shown?] false )))

(re-frame/reg-event-db
 ::close-check-results
 (fn [db _]
   (assoc-in db [::check-results :shown?] false )))

(re-frame/reg-event-db
 ::edit-payment-bank-account
 (fn [db [_ f v]]
   (assoc-in db [::advanced-print-checks :bank-account-id] v)))

(re-frame/reg-event-db
 ::edit-payment
 (fn [db [_ which f v]]
   (update-in db [::advanced-print-checks :invoices]
              (fn [is]
                (for [i is]
                  (if (= which (:id i))
                    (assoc-in i f v)
                    i))))))

(defn print-checks-query [invoice-payments bank-account-id type client-id]
  {:venia/operation {:operation/type :mutation
                     :operation/name "PrintChecks"}
   
   :venia/queries [[:print-checks
                    {:invoice_payments invoice-payments
                     :type type
                     :bank_account_id bank-account-id
                     :client_id client-id}
                    [[:invoices invoice-read]
                     :pdf_url]]]})

(re-frame/reg-event-fx
 ::print-checks
 (fn [{:keys [db]} [_ bank-account-id type]]
   {:db (-> db
            (assoc-in [::invoice-page :print-checks-shown?] false )
            (assoc-in [::invoice-page :print-checks-loading?] true ))
    :graphql
    {:token (-> db :user)
     
     :query-obj (print-checks-query (map (fn [[id invoice]]
                                           {:invoice-id id
                                            :amount (:outstanding-balance invoice)})
                                         (get-in db [::invoice-page :checked]))
                                    bank-account-id
                                    type
                                    (:client db))  
     :on-success [::checks-created]}}))



(re-frame/reg-event-fx
 ::advanced-print-checks-submitted
 (fn [{:keys [db]} [_ bank-account-id]]
   (let [invoice-amounts (by :id (comp js/parseFloat :amount) (get-in db [::advanced-print-checks :invoices]))
         bank-account-id (get-in db [::advanced-print-checks :bank-account-id])
         type (->> @(re-frame/subscribe [::subs/client])
                   :bank-accounts
                   (filter #(= bank-account-id (:id %)))
                   first
                   :type)]
     {:db (-> db
              (assoc-in [::advanced-print-checks :printing?] true ))
      :graphql
      {:token (-> db :user)
       
       :query-obj (print-checks-query (map (fn [x]
                                             {:invoice-id (:id x)
                                              :amount (invoice-amounts (:id x))})
                                           (get-in db [::advanced-print-checks :invoices]))
                                      bank-account-id
                                      (cond (= type :check)
                                            :check
                                            (= type :cash)
                                            :cash

                                            :else
                                            :check) 
                                      (:client db))  

       :on-success [::checks-created]}})))

(re-frame/reg-event-fx
 ::checks-created
 (fn [{:keys [db]} [_ data]]
   (let [{{:keys [pdf-url invoices]} :print-checks} data
         invoices-by-id (by :id invoices) ]
     {
      :db (-> db
              (update-in [::invoice-page :invoices]
                            (fn [invoices]
                              (map (fn [i]
                                     (merge i (invoices-by-id (:id i))))
                                   invoices)))
              (assoc-in [::invoice-page :checked] nil)
              (assoc-in [::invoice-page :print-checks-loading?] false)
              (assoc-in [::advanced-print-checks :printing?] false)
              (assoc-in [::advanced-print-checks :shown?] false)
              (assoc-in [::check-results :shown?] true)
              (assoc-in [::check-results :pdf-url] pdf-url)
              )})))

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

(re-frame/reg-event-fx
 ::new-invoice
 (fn [{:keys [db]} _]
   {:dispatch [::events/modal-status ::new-invoice {:visible? true}]
    :db (assoc-in db [::new-invoice] {:client-id (:id @(re-frame/subscribe [::subs/client]))
                                      :date (date->str (c/now) standard)
                                      :location (first (:locations @(re-frame/subscribe [::subs/client])))})}))

(re-frame/reg-event-fx
 ::edit-invoice
 (fn [{:keys [db]} [_ which]]
   (let [edit-invoice (update which :date #(date->str % standard))
         edit-invoice (assoc edit-invoice :original edit-invoice)]
     {:dispatch [::events/modal-status ::edit-invoice {:visible? true}]
      :db (assoc-in db [::edit-invoice] edit-invoice)})))



(re-frame/reg-event-fx
 ::create-invoice
 (fn [{:keys [db]} _]
   (let [new-invoice @(re-frame/subscribe [::new-invoice])]
     {:graphql
      {:token (-> db :user)
       :query-obj {:venia/operation {:operation/type :mutation
                                     :operation/name "AddInvoice"}
                   
                   :venia/queries [{:query/data [:add-invoice
                                                 {:invoice new-invoice}
                                                 invoice-read]}]}  
       :on-success [::invoice-created]
       :on-error [::invoice-create-failed]}})))



(re-frame/reg-event-fx
 ::edit-invoice-save
 (fn [{:keys [db]} _]
   (let [{:keys [date total invoice-number id]} @(re-frame/subscribe [::edit-invoice])]
     {:graphql
      {:token (-> db :user)
       :query-obj {:venia/operation {:operation/type :mutation
                                     :operation/name "EditInvoice"}
                   
                   :venia/queries [{:query/data [:edit-invoice
                                                 {:invoice {:id id :invoice-number invoice-number :date date :total total}}
                                                 invoice-read]}]}  
       :on-success [::invoice-edited]
       :on-error [::invoice-edit-failed]}})))

(re-frame/reg-event-fx
 ::unvoid-invoice
 (fn [{:keys [db]} [_ {id :id}]]
   {:graphql
    {:token (-> db :user)
     :query-obj {:venia/operation {:operation/type :mutation
                                   :operation/name "UnvoidInvoice"}
                 
                 :venia/queries [{:query/data [:unvoid-invoice
                                               {:invoice-id id}
                                               invoice-read]}]}  
     :on-success [::invoice-unvoided]}}))

(re-frame/reg-event-fx
 ::void-invoice
 (fn [{:keys [db]} [_ {id :id}]]
   {:graphql
    {:token (-> db :user)
     :query-obj {:venia/operation {:operation/type :mutation
                                   :operation/name "VoidInvoice"}
                 
                 :venia/queries [{:query/data [:void-invoice
                                               {:invoice-id id}
                                               invoice-read]}]}  
     :on-success [::invoice-voided]}}))

(re-frame/reg-event-fx
 ::handwrite-checks-save
 (fn [{:keys [db]} _]
   (let [{:keys [date invoice amount check-number bank-account-id]} @(re-frame/subscribe [::handwrite-checks])]
     {:graphql
      {:token (-> db :user)
       :query-obj {:venia/operation {:operation/type :mutation
                                     :operation/name "AddHandwrittenCheck"}
                   
                   :venia/queries [{:query/data [:add-handwritten-check
                                                 {:date date
                                                  :amount amount
                                                  :check-number check-number
                                                  :bank-account-id bank-account-id
                                                  :invoice_id (:id invoice)
                                                  }
                                                 [[:invoices invoice-read]]]}]}  
       :on-success [::handwrite-checks-succeeded]}})))

(re-frame/reg-event-fx
 ::handwrite-checks-succeeded
 (fn [{:keys [db]} [_ {:keys [add-handwritten-check] :as result}]]
   (let [invoices-by-id (by :id (:invoices add-handwritten-check))]
     {:dispatch [::events/modal-completed ::handwrite-checks]
      :db (-> db
              (update-in [::invoice-page :invoices]
                         (fn [invoices]
                           (map (fn [i]
                                  (merge i (invoices-by-id (:id i))))
                                invoices)))
              (dissoc ::handwrite-checks))})))

(re-frame/reg-event-fx
 ::invoice-create-failed
 (fn [{:keys [db]} [_ data]]
   {:dispatch [::events/modal-failed ::new-invoice (:message data)]}))

(re-frame/reg-event-fx
 ::invoice-created
 (fn [{:keys [db]} [_ {:keys [add-invoice]}]]
   {:dispatch [::events/modal-completed ::new-invoice]
    :db (-> db
            (update-in [::invoice-page :invoices]
                       (fn [is]
                         (into [(assoc add-invoice :class "live-added")]
                               is)))
            (dissoc ::new-invoice))}))

(re-frame/reg-event-fx
 ::invoice-edited
 (fn [{:keys [db]} [_ {:keys [edit-invoice]}]]
   {:dispatch [::events/modal-completed ::edit-invoice]
    :db (-> db
            (update-in [::invoice-page :invoices]
                       (fn [is]
                         (mapv (fn [i]
                                (if (= (:id i) (:id edit-invoice))
                                  (assoc edit-invoice :class "live-added")
                                  i)) is)))
            (dissoc ::edit-invoice))}))


(re-frame/reg-event-fx
 ::invoice-edit-failed
 (fn [{:keys [db]} [_ data]]
   {:dispatch [::events/modal-failed ::edit-invoice "That invoice already exists."]}))

(re-frame/reg-event-fx
 ::invoice-unvoided
 (fn [{:keys [db]} [_ {:keys [unvoid-invoice]}]]
   {:db (-> db
            (update-in [::invoice-page :invoices]
                       (fn [is]
                         (mapv (fn [i]
                                 (if (= (:id i) (:id unvoid-invoice))
                                   (assoc unvoid-invoice :class "live-removed")
                                   i)) is))))}))

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



(re-frame/reg-event-fx
 ::expense-accounts-updated
 (fn [{:keys [db]} [_ data]]
   (let [updated (:edit-expense-accounts data)]
     {:dispatch [::events/modal-completed ::expense-accounts-dialog/change-expense-accounts]
      :db (-> db
              (update-in [::invoice-page :invoices]
                         
                         (fn [is]
                           
                           (replace-if #(= (:id %1) (:id %2)) updated is)))
              (dissoc ::change-expense-accounts))})))

(defn print-checks-modal []
  (let [{:keys [checked]} @(re-frame/subscribe [::invoice-page]) 
        {:keys [shown? invoices printing?] :as advanced-print-checks} @(re-frame/subscribe [::advanced-print-checks])
        current-client @(re-frame/subscribe [::subs/client])] 

    (when shown?
      [modal {:title "Print Checks"
              :foot [:button.button.is-primary {:on-click (dispatch-event [::advanced-print-checks-submitted])
                                                :disabled (cond printing?
                                                                "disabled"

                                                                (seq (filter #(> (js/parseFloat (:amount %)) (js/parseFloat (:outstanding-balance %))) invoices))
                                                                "disabled"

                                                                :else
                                                                "")
                                                :class (if printing? "is-loading" "")}
                     [:span "Print"]]
              :hide-event [::cancel-advanced-print]}
       "Print using"
       [:span.field
        [:span.select
         [bind-field
          
          [:select {:type "select"
                    :field :bank-account-id
                    :event ::edit-payment-bank-account
                    :subscription advanced-print-checks}
           (for [{:keys [id number name]} (:bank-accounts current-client)]
             ^{:key id} [:option {:value id} name])]]]]

       [:table.table.is-fullwidth
        [:thead
         [:tr
          [:th "Vendor"]
          [:th "Invoice ID"]
          [:th {:style {"width" "10em"}} "Payment"]]]
        [:tbody
         (for [{:keys [vendor payment outstanding-balance invoice-number id] :as i} invoices]
           ^{:key id}
           [:tr
            [:td (:name vendor)]
            [:td invoice-number]
            
            [:td  [:div.field.has-addons.is-extended
                   [:p.control [:a.button.is-static "$"]]
                   [:p.control
                    [bind-field
                     [:input.input {:type "number"
                                    :field :amount
                                    :event [::edit-payment id]
                                    :subscription i
                                    :value payment
                                    :max outstanding-balance
                                    :step "0.01"}]]]]]])]]])))

(defn handwrite-checks-modal []
  (let [{:keys [checked]} @(re-frame/subscribe [::invoice-page]) 
        {:keys [invoice] :as handwrite-checks} @(re-frame/subscribe [::handwrite-checks])
        change-event [::events/change-form [::handwrite-checks]]
        current-client @(re-frame/subscribe [::subs/client])] 

    [action-modal {:id ::handwrite-checks
                   :title "Handwrite Check"
                   :action-text "Save"
                   :save-event [::handwrite-checks-save]
                   #_#_:can-submit? (s/valid? ::invoice/invoice data)}
     [horizontal-field
      [:label.label  "Pay using"]
      [:span.select
       [bind-field
        [:select {:type "select"
                  :field :bank-account-id
                  :event change-event
                  :subscription handwrite-checks}
         (for [{:keys [id number name]} (:bank-accounts current-client)]
           ^{:key id} [:option {:value id} name])]]]]

     [horizontal-field
      [:label.label "Paid amount"]
      [:div.field.has-addons.is-extended
       [:p.control [:a.button.is-static "$"]]
       [:p.control
        [bind-field
         [:input.input {:type "number"
                        :field [:amount]
                        :event change-event
                        :subscription handwrite-checks
                        :spec ::invoice/total
                        :step "0.01"}]]]]]

     [horizontal-field
      [:label.label  "Date"]
      [bind-field
       [:input.input {:type "date"
                      :field [:date]
                      :event change-event
                      :spec ::invoice/date
                      :subscription handwrite-checks}]]]

     [horizontal-field
      [:label.label  "Check number"]
      [bind-field
       [:input.input {:type "number"
                      :field [:check-number]
                      :event change-event
                      #_#_:spec ::check/date
                      :subscription handwrite-checks}]]]]))

(re-frame/reg-event-fx
 ::change-new-invoice-client
 (fn  [{:keys [db ]} [_ location field value]]
   (let [first-location (-> @(re-frame/subscribe [::subs/clients-by-id])
                            (get-in [value :locations])
                            first)]
     {:dispatch [::events/change-form location field value]
      :db (-> db
              (assoc-in [::new-invoice :location] first-location))})))

(defn new-invoice-modal []
  (let [data @(re-frame/subscribe [::new-invoice])
        change-event [::events/change-form [::new-invoice]]
        locations (get-in @(re-frame/subscribe [::subs/clients-by-id]) [(:client-id data) :locations])
        should-select-location? (and locations
                                    (> (count locations) 1))]
    [action-modal {:id ::new-invoice
                   :title "New Invoice"
                   :action-text "Create"
                   :save-event [::create-invoice]
                   :can-submit? (s/valid? ::invoice/invoice data)}
     
     (when-not @(re-frame/subscribe [::subs/client])
       [horizontal-field
        [:label.label  "Client"]
        [bind-field
         [typeahead {:matches (map (fn [x] [(:id x) (:name x)]) @(re-frame/subscribe [::subs/clients]))
                     :type "typeahead"
                     :field [:client-id]
                     :event [::change-new-invoice-client [::new-invoice]]
                     :spec ::invoice/client-id
                     :subscription data}]]])
     (when should-select-location?
       [horizontal-field
        [:label.label  "Location"]
        [:div.select
         [bind-field
          [:select {:type "select"
                    :field [:location]
                    :spec (set locations)
                    :event change-event
                    :subscription data}
           (map (fn [l] [:option {:value l} l]) locations)]]]])

     [horizontal-field
      [:label.label  "Vendor"]
      [bind-field
       [typeahead {:matches (map (fn [x] [(:id x) (:name x)]) @(re-frame/subscribe [::subs/vendors]))
                   :type "typeahead"
                   :auto-focus true
                   :field [:vendor-id]
                   :text-field [:vendor-name]
                   :event change-event
                   :spec (s/nilable ::invoice/vendor-id)
                   :subscription data}]]]
     [horizontal-field
      [:label.label  "Date"]

      
      [bind-field
       [:input.input {:type "date"
                      :field [:date]
                      :event change-event
                      :spec ::invoice/date
                      :subscription data}]]] 

     

     [horizontal-field
      [:label.label  "Invoice #"]
      [bind-field
       [:input.input {:type "text"
                      :field [:invoice-number]
                      :event change-event
                      :spec ::invoice/invoice-number
                      :subscription data}]]]

     [horizontal-field
      [:label.label "Total"]
      [:div.field.has-addons.is-extended
       [:p.control [:a.button.is-static "$"]]
       [:p.control
        [bind-field
         [:input.input {:type "number"
                        :field [:total]
                        :event change-event
                        :subscription data
                        :spec ::invoice/total
                        :step "0.01"}]]]]]
     ]))

(defn edit-invoice-modal [{:keys [can-change-amount?]}]
  (let [data @(re-frame/subscribe [::edit-invoice])
        change-event [::events/change-form [::edit-invoice]]
        locations (get-in @(re-frame/subscribe [::subs/clients-by-id]) [(:client-id data) :locations])
        min-total (if (= (:total (:original data)) (:outstanding-balance (:original data)))
                    nil
                    
                    (- (:total (:original data)) (:outstanding-balance (:original data))))
        
        should-select-location? (and locations
                                    (> (count locations) 1))]
    [action-modal {:id ::edit-invoice
                   :title "Update Invoice"
                   :action-text "Save"
                   :save-event [::edit-invoice-save]
                   :can-submit? (and #_(s/valid? ::invoice/invoice data)
                                     (or (not min-total) (>= (:total data) min-total)))}
     
     [horizontal-field
      [:label.label  "Date"]

      
      [bind-field
       [:input.input {:type "date"
                      :field [:date]
                      :event change-event
                      :spec ::invoice/date
                      :subscription data}]]] 

     

     [horizontal-field
      [:label.label  "Invoice #"]
      [bind-field
       [:input.input {:type "text"
                      :field [:invoice-number]
                      :event change-event
                      :spec ::invoice/invoice-number
                      :subscription data}]]]

     [horizontal-field
      [:label.label "Total"]
      [:div.field.has-addons.is-extended
       [:p.control [:a.button.is-static "$"]]
       [:p.control
        [bind-field
         [:input.input {:type "number"
                        :field [:total]
                        :disabled (if can-change-amount? "" "disabled")
                        :event change-event
                        :min min-total
                        :subscription data
                        :spec ::invoice/total
                        :step "0.01"}]]]]]]))

(re-frame/reg-event-db
 ::change-selected-vendor
 (fn [db [_ key value]]
   (let [[key] key 
         updated (assoc-in db [::invoice-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 :start 0)])
         (assoc-in updated [::params :vendor-id] value))
       updated))))

(re-frame/reg-event-fx
 ::invoice-number-like-current-changed
 (fn [{:keys [db]} [_ params invoice-like]]
   {:db (assoc-in db [::params :invoice-number-like-current] invoice-like )
    :dispatch-debounce {:event [::invoice-number-like-settled invoice-like]
                        :time 500
                        :key ::invoice-nuber-like}}))

(re-frame/reg-event-fx
 ::invoice-number-like-settled
 (fn [{:keys [db]} [_ invoice-like]]
   {:dispatch [::params-change (assoc (::params db) :invoice-number-like invoice-like :start 0) ]}))

(defn invoice-number-filter []
  (let [{:keys [invoice-number-like-current] :as params} @(re-frame/subscribe [::params])]
    [:div.field
     [:div.control [:input.input {:placeholder "AP-123"
                                  :value invoice-number-like-current
                                  :on-change (fn [x]
                                               (re-frame/dispatch [::invoice-number-like-current-changed params (.. x -target -value) ]))} ]]]))

(defn pay-button [{:keys [print-checks-shown? checked-invoices print-checks-loading?]}]
  (let [current-client @(re-frame/subscribe [::subs/client])]
    [:div
     
     
     
     [:div.is-pulled-right
      
      
      [:button.button.is-danger {:on-click (dispatch-event [::new-invoice])} "New Invoice"]
      
      
      (when current-client
        [:div.dropdown.is-right {:class (if print-checks-shown?
                                          "is-active"
                                          "")}
         [:div.dropdown-trigger
          [:button.button.is-success {:aria-haspopup true
                                      :on-click (dispatch-event [::print-checks-clicked ])
                                      :disabled (if (and (seq checked-invoices)
                                                         (->> checked-invoices
                                                              vals
                                                              (group-by #(get-in % [:vendor :id]))
                                                              (reduce-kv (fn [negative? _ invoices]
                                                                           (or negative? (< (reduce + 0 (map (fn [x] (-> x :outstanding-balance js/parseFloat)) invoices) ) 0)))
                                                                         false)
                                                              not))
                                                  ""
                                                  "disabled")

                                      :class (if print-checks-loading?
                                               "is-loading"
                                               "")}
           "Pay "
           (when (> (count checked-invoices ))
             (str 
              (count checked-invoices)
              " invoices "
              "(" (->> checked-invoices
                         vals
                         (map (comp js/parseFloat :outstanding-balance))
                         (reduce + 0)
                         (gstring/format "$%.2f"  ))
              ")"))
           
           
           [:span " "]
           [:span.icon.is-small [:i.fa.fa-angle-down {:aria-hidden "true"}]]]]
         [:div.dropdown-menu {:role "menu"}
          [:div.dropdown-content
           (list
            (for [{:keys [id number name type]} (:bank-accounts current-client)]
              (if (= :cash type)
                ^{:key id} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :cash])} "With cash"]
                (list
                 ^{:key (str id "-check")} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :check])} "Print checks from " name]
                 ^{:key (str id "-debit")} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :debit])} "Debit from " name])))
            ^{:key "advanced-divider"} [:hr.dropdown-divider]

            (when (= 1 (count checked-invoices))
              ^{:key "handwritten"} [:a.dropdown-item {:on-click (dispatch-event [::handwrite-checks])} "Handwritten Check..."])
            ^{:key "advanced"} [:a.dropdown-item {:on-click (dispatch-event [::advanced-print-checks])} "Advanced..."])]]])]
     [:div.is-pulled-right
      (into [:div.tags {:style {:margin-right ".5 rem;"}}] (map (fn [[id invoice]] [:span.tag.is-medium (:invoice-number invoice) [:button.delete.is-small {:on-click (dispatch-event [::toggle-check id invoice])}]]) checked-invoices))]]
    ))

(defn unpaid-invoices-content [{:keys [status]}]
  (r/create-class {:display-name "unpaid-invoices-content"
                   :component-will-unmount (fn [this]
                                             (re-frame/dispatch [::unmount-invoices])

                                             )
                   :reagent-render (fn [{:keys [status]}]
                                     (let [{:keys [checked print-checks-shown? print-checks-loading? advanced-print-shown? vendor-filter]} @(re-frame/subscribe [::invoice-page]) 
                                           current-client @(re-frame/subscribe [::subs/client])
                                           {check-results-shown? :shown? pdf-url :pdf-url} @(re-frame/subscribe [::check-results])]
                                       [:div 
                                        [:h1.title (str (str/capitalize status) " invoices")]
                                        (when (= status "unpaid")
                                          [pay-button {:print-checks-shown? print-checks-shown? :checked-invoices checked :print-checks-loading? print-checks-loading?}])

                                        
                                        
                                        [invoice-table {:id :unpaid
                                                        :params (re-frame/subscribe [::params])
                                                        :invoice-page (re-frame/subscribe [::invoice-page])
                                                        :status (re-frame/subscribe [::subs/status])
                                                        :on-edit-invoice (fn [which]
                                                                           (re-frame/dispatch [::edit-invoice which]))
                                                        :on-unvoid-invoice (fn [which]
                                                                           (re-frame/dispatch [::unvoid-invoice which]))

                                                        :on-void-invoice (fn [which]
                                                                           (re-frame/dispatch [::void-invoice which]))
                                                        :on-params-change (fn [params]
                                                                            (re-frame/dispatch [::params-change params]))
                                                        :check-boxes (= status "unpaid")
                                                        :checked checked
                                                        :on-check-changed (fn [which invoice]
                                                                            (re-frame/dispatch [::toggle-check which invoice]))
                                                        :expense-event [::expense-accounts-dialog/change-expense-accounts]}]

                                        [print-checks-modal]
                                        [new-invoice-modal]
                                        [edit-invoice-modal {:can-change-amount? (= status "unpaid")}]
                                        [handwrite-checks-modal]
                                        [change-expense-accounts-modal {:updated-event [::expense-accounts-updated]}]
                                        (when check-results-shown?
                                          (if pdf-url
                                            [modal
                                             {:title "Your checks are ready!"
                                              :hide-event [::close-check-results]}
                                             [:div "Click " [:a {:href pdf-url :target "_new"} "here"] " to print them."]
                                             [:div [:em "Remember to turn off all scaling and margins."]]
                                             ]
                                            [modal
                                             {:title "Payment created!"
                                              :hide-event [::close-check-results]}
                                             [:div [:em "Your payment was created."]]
                                             ]))

                                        ]))
                   :component-will-mount #(re-frame/dispatch-sync [::params-change {:status status}]) }))

(defn unpaid-invoices-page [{:keys [status]}]
  [side-bar-layout {:side-bar [invoices-side-bar {}
                               ^{:key "extra-filter"}
                               [:div
                                [:p.menu-label "Vendor"]
                                [:div [vendor-filter {:on-change-event [::change-selected-vendor]
                                                      :value (:vendor-filter @(re-frame/subscribe [::invoice-page]))
                                                      :vendors @(re-frame/subscribe [::subs/vendors])}]]
                                [:p.menu-label "Invoice #"]
                                [:div 
                                 [invoice-number-filter]]]]
                    :main [unpaid-invoices-content {:status status}]
                    :bottom [vendor-dialog {:vendor @(re-frame/subscribe [::subs/user-editing-vendor])
                                            :save-event [::events/save-vendor]
                                            :change-event [::events/change-nested-form-state [:user-editing-vendor]] :id :auto-ap.views.main/user-editing-vendor}]}])
