(ns auto-ap.views.components.invoice-table
  (:require [re-frame.core :as re-frame]
            [auto-ap.subs :as subs]
            [auto-ap.views.utils :refer [date->str dispatch-event delayed-dispatch]]
            [auto-ap.views.components.paginator :refer [paginator]]
            [auto-ap.views.components.sorter :refer [sorted-column]]
            [reagent.core :as reagent]
            [clojure.string :as str]
            [cljs-time.format :as format]
            [goog.string :as gstring]))

;; TODO graphql schema enforcement
;; TODO postgres constraints for data integrity
;; TODO performance
;; TODO refactor graphql

(re-frame/reg-event-fx
 ::toggle-checks
 (fn  [{:keys [db] } [_ invoice-id]]
   {:db
    (update-in db [::visible-checks] (fn [i] (if (= i invoice-id) nil invoice-id) ))}))

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

(re-frame/reg-event-fx
 ::toggle-expense-accounts
 (fn  [{:keys [db] } [_ invoice-id]]
   {:db
    (update-in db [::visible-expense-accounts] (fn [i] (if (= i invoice-id) nil invoice-id) ))}))

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



(defn query [params]
  {:venia/queries [[:invoice_page
                    (assoc params
                           :client-id (:id @(re-frame/subscribe [::subs/client]))) 
                    [[:invoices [:id :total :outstanding-balance :invoice-number :date :status
                                 [:vendor [:name :id]]
                                 [:expense_accounts [:amount :id :expense_account_id :location
                                                     [:expense_account [:id :name :location [:parent [:id :name]]]]]]
                                 [:client [:name :id :locations]]
                                 [:payments [:amount :id [:payment [:id :status :amount :s3_url :check_number
                                                                    [:transaction [:post_date]]]]]]]]
                     :total
                     :start
                     :end]]]})



(defn invoice-table [{:keys [id invoice-page status on-params-change vendors params check-boxes checked on-check-changed on-edit-invoice on-void-invoice on-unvoid-invoice expense-event]}]
  (let [visible-checks @(re-frame/subscribe [::visible-checks])
        visible-expense-accounts @(re-frame/subscribe [::visible-expense-accounts])
        selected-client @(re-frame/subscribe [::subs/client])
        opc (fn [p]
              (on-params-change (merge @params p)))]
    (fn [{:keys [id invoice-page status on-params-change vendors checked params]}]
      (let [{:keys [sort-by asc]} @params
            {:keys [invoices start end count total]} @invoice-page
            visible-checks @(re-frame/subscribe [::visible-checks])
            visible-expense-accounts @(re-frame/subscribe [::visible-expense-accounts])
            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 check-boxes
              [:th {:style {"width" "20px"}}])
            
            (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 "invoice-number"
                            :sort-by sort-by
                            :asc asc}
             "Invoice #"]
            [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 "location"
                            :sort-by sort-by
                            :asc asc}
             "Location"]
            [sorted-column {:on-sort opc
                            :style {:width "8em" :cursor "pointer"}
                            :sort-key "total"
                            :sort-by sort-by
                            :asc asc}
             "Amount"]

            [sorted-column {:on-sort opc
                            :style {:width "10em" :cursor "pointer"}
                            :sort-key "outstanding-balance"
                            :sort-by sort-by
                            :asc asc}
             "Outstanding"]
            
            [:th {
                            :style {:width "15em" :cursor "pointer"}
                            
                            
                            }
             ""]]]
          [:tbody
           
           (if (:loading @status)
             [:tr 
              [:td {:col-span 5}
               [:i.fa.fa-spin.fa-spinner]]]
             
             (for [{:keys [client payments expense-accounts invoice-number date total outstanding-balance id vendor] :as i} (:invoices @invoice-page)]
               ^{:key id}
               [:tr {:class (:class i)}
                (when check-boxes
                  [:td [:input.checkbox {:type "checkbox"
                                         :checked (if (get checked id)
                                                    "checked"
                                                    "")
                                         :on-change (fn [x e] (when on-check-changed
                                                                
                                                               (on-check-changed id i)))} ]])
                (when-not selected-client
                  [:td (:name client)])
                [:td (:name vendor)]
                [:td invoice-number]
                [:td (date->str date) ]
                [:td (str/join ", " (set (map :location expense-accounts)))]

                [:td (gstring/format "$%.2f" total )]
                [:td (gstring/format "$%.2f" outstanding-balance )]
                [:td.expandable
                 (when (seq expense-accounts)

                   [:div.dropdown.is-right {:class (if (= id visible-expense-accounts)
                                                     "is-active"
                                                     "")}
                    [:div.dropdown-trigger
                     [:a.button.badge {:data-badge (str (clojure.core/count expense-accounts))
                                       :aria-haspopup true
                                       :tab-index "0"
                                       
                                       :on-blur (delayed-dispatch [::toggle-expense-accounts id]) 
                                       :on-focus (dispatch-event [::toggle-expense-accounts id])
                                       } "Accounts"]]
                    [:div.dropdown-menu {:role "menu"}
                     [:div.dropdown-content
                      (for [e expense-accounts]
                        ^{:key (:id e)}
                        [:span.dropdown-item  (:name (:expense-account e)) " "  (gstring/format "$%.2f" (:amount e) ) ])

                      [:hr.dropdown-divider]

                      (when expense-event
                        [:a.dropdown-item.is-primary {:on-click (dispatch-event (conj expense-event i))} "Change"])]]])
                 [:span {:style {:margin-left "1em"}}]
                 
                 (when (and on-edit-invoice (not= ":voided" (:status i)))
                   [:button.button {:on-click (fn [] (on-edit-invoice i))} [:span.icon [:i.fa.fa-pencil]]])
                 (when (and on-void-invoice (= (:outstanding-balance i) (:total i)) (not= ":voided" (:status i)))
                   [:button.button.is-outlined {:on-click (fn [] (on-void-invoice i))} [:span.icon [:span.icon-bin-2 {:style {:font-weight "400"}}]]])
                 (when (and on-unvoid-invoice (= ":voided" (:status i)))
                   [:button.button.is-outlined {:on-click (fn [] (on-unvoid-invoice i))} [:span [:span.icon [:i.fa.fa-undo]]]])
                 (when (seq payments)

                   [:div.dropdown.is-right {:class (if (= id visible-checks)
                                                     "is-active"
                                                     "")}
                    [:div.dropdown-trigger
                     [:a.button.badge {:data-badge (str (clojure.core/count payments))
                                       :aria-haspopup true
                                       :tab-index "0"
                                       
                                       :on-blur (delayed-dispatch [::toggle-checks id])
                                       :on-focus (dispatch-event [::toggle-checks id])
                                       } "Checks"]]
                    [:div.dropdown-menu {:role "menu"}
                     [:div.dropdown-content
                      (for [payment payments]
                         (if (:s3-url (:payment payment))
                          ^{:key (:id payment)}
                          [:a.dropdown-item {:href (:s3-url (:payment payment)) :target "_new"} [:i.fa.fa-money-check] [:span.icon [:i.fa.fa-money]] (str  " " (:check-number (:payment payment)) " (" (gstring/format "$%.2f" (:amount payment) ) ")")]

                          ^{:key (:id payment)}
                          [:span.dropdown-item  [:span.icon {:class [(when (= :cleared (:status (:payment payment)))
                                                                       "has-text-success")]}
                                                 [:i.fa.fa-money]] (str  " " (:check-number (:payment payment)) " (" (gstring/format "$%.2f" (:amount payment) ) ") "
                                                                         (when (= :cleared (:status (:payment payment)))
                                                                           (str " - " (:post-date (:transaction (:payment payment))))))]))]]])
                 
                 ]]))]]]))))
