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


(re-frame/reg-sub
 ::transaction-page
 (fn [db]
   (-> db ::transaction-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 [[:transaction_page
                                           (assoc params :client-id (:id @(re-frame/subscribe [::subs/client]))) 
                                           [[:transactions [:id
                                                            :amount
                                                            :date
                                                            :post_date
                                                            :status
                                                            :description_original
                                                            [:payment [:check_number :s3_url]]
                                                            [:client [:name :id]]
                                                            [:bank-account [:name :yodlee-account-id]]]]
                                            :total
                                            :start
                                            :end]]]} 
              :on-success [::received]}}))

(re-frame/reg-event-db
 ::received
 (fn [db [_ data]]
   (-> db
       (assoc ::transaction-page (first (:transaction-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-bank-account
 (fn [db [_ key value]]
   (let [[key] key 
         updated (assoc-in db [::transaction-page :bank-account-filter key] value)]
     (if (and (= key :id)
              (not= value (get-in db [::params :bank-account-id])))
       (do
         (re-frame/dispatch [::params-change (assoc (::params updated) :bank-account-id value)])
         (assoc-in updated [::params :bank-account-id] value))
       updated))))

(defn transaction-table [{:keys [id transaction-page status on-params-change vendors params check-boxes checked on-check-changed expense-event]}]
  (let [opc (fn [p]
              (on-params-change (merge @params p )))]
    (fn [{:keys [id transaction-page status on-params-change vendors checked]}]
      (let [{:keys [sort-by asc]} @params
            {:keys [transactions start end count total]} @transaction-page
            selected-client @(re-frame/subscribe [::subs/client])
            percentage-size (if selected-client "25%" "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 "description-original"
                            :sort-by sort-by
                            :asc asc}
             "Description"]
            [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 {:width percentage-size} "Bank account"]
            [:th {:width percentage-size} "Yodlee bank account"]
            
            
            [:th {:style {:width "10em"}} "" ]]]
          [:tbody
           (if (:loading @status)
             [:tr 
              [:td {:col-span 5}
               [:i.fa.fa-spin.fa-spinner]]]
             (for [{:keys [client check status bank-account description-original date amount id ] :as i} (:transactions @transaction-page)]
               ^{:key id}
               [:tr {:class (:class i)}
                
                (when-not selected-client
                  [:td (:name client)])
                [:td description-original]
                [:td (date->str date) ]
                [:td (gstring/format "$%.2f" amount )]
                [:td status]
                [:td (:name bank-account )]
                [:td (:yodlee-account-id bank-account )]

                [:td
                 
                 (when check
                   [:a.tag {:href (:s3-url check) :target "_new"} [:i.fa.fa-money-check] [:span.icon [:i.fa.fa-money]] (str  " " (:check-number check) " (" (gstring/format "$%.2f" amount ) ")")])]
                ]))]]]))))

(re-frame/reg-event-fx
 ::manual-yodlee-import
 (fn [{:keys [db]} _]
   {:dispatch [::events/modal-status ::manual-yodlee-import {:visible? true}]
    :db (assoc-in db [::manual-yodlee-import] {:client-id (:id @(re-frame/subscribe [::subs/client]))
                                               :data ""})}))

(re-frame/reg-sub
 ::manual-yodlee-import
 (fn [db]
   (-> db ::manual-yodlee-import)))

(re-frame/reg-event-fx
 ::manual-yodlee-import-completed
 (fn [{:keys [db]} [_ {:keys [imported errors]}]]
   (re-frame/dispatch [::params-change {}])
   {:dispatch [::events/modal-completed ::manual-yodlee-import]
    :db (-> db
            (assoc-in [::notification :message] (str "Successfully imported " imported " transactions"))
            (assoc-in [::notification :errors] errors))}))

(re-frame/reg-event-fx
 ::manual-yodlee-import-started
 (fn [{:keys [db]} _]
   (let [manual-yodlee-import (::manual-yodlee-import db)]
     {:http {:token (:user db)
             :method :post 
             :body (pr-str manual-yodlee-import)
             :headers {"Content-Type" "application/edn"}
             :uri (str "/api/transactions/batch-upload")
             :on-success [::manual-yodlee-import-completed]
             :on-error [::manual-yodlee-import-error]}})))


(defn manual-yodlee-import-modal []
  (let [data @(re-frame/subscribe [::manual-yodlee-import])
        change-event [::events/change-form [::manual-yodlee-import]]]
    [action-modal {:id ::manual-yodlee-import
                   :title "Manual Yodlee Import"
                   :action-text "Import"
                   :save-event [::manual-yodlee-import-started]}
     [:div.field
      [:label.label
       "Yodlee manual import table"]
      [:div.control
       [bind-field
        [:textarea.textarea {:field [:data]
                             :event change-event
                             :subscription data}]]]]]))

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

(def transactions-content
  
  (with-meta
    (fn []
      (let [notification (re-frame/subscribe [::notification])
            current-client @(re-frame/subscribe [::subs/client])
            user @(re-frame/subscribe [::subs/user])]
        
        [:div 
         [:h1.title "Transactions"]
         (when (= "admin" (:user/role user))
           (list
            (when (:message @notification)
              
              (list
               [:div.notification
                (:message @notification)
                ]
               (when (seq (:errors @notification))
                 [:div.notification.is-danger
                  [:h3 (count (:errors @notification)) " errors:"] 
                  
                  [:ul
                   (for [transaction (:errors @notification)
                         error (:errors transaction)]
                     [:li (:description-original transaction) "-" (:details error)])
                   ]])))
            
            [:div.is-pulled-right
             [:button.button.is-danger {:on-click (dispatch-event [::manual-yodlee-import])}
              "Manual Yodlee Import"]]))
         [transaction-table {:id :transactions
                             :params (re-frame/subscribe [::params])
                             :transaction-page (re-frame/subscribe [::transaction-page])
                             :status (re-frame/subscribe [::subs/status])
                             :on-params-change (fn [params]
                                                 (re-frame/dispatch [::params-change params]))}]
         [manual-yodlee-import-modal]]))
    {:component-will-mount #(re-frame/dispatch-sync [::params-change {}]) }))
(defn transactions-page []
  [side-bar-layout {:side-bar [:div
                               [:p.menu-label "Bank Account"]

                               [:div 
                               [bank-account-filter {:on-change-event [::change-selected-bank-account]
                                                     :value (:bank-acount-filter @(re-frame/subscribe [::transaction-page]))
                                                     :bank-accounts @(re-frame/subscribe [::subs/bank-accounts])}]]]
                    :main [transactions-content]}])

