(ns auto-ap.views.pages.transactions
  (:require [auto-ap.effects.forward :as forward]
            [auto-ap.forms :as forms]
            [auto-ap.subs :as subs]
            [auto-ap.utils :refer [replace-by]]
            [auto-ap.views.components.layouts
             :refer
             [appearing-side-bar side-bar-layout]]
            [auto-ap.views.pages.data-page :as data-page]
            [auto-ap.views.pages.transactions.common :refer [transaction-read]]
            [auto-ap.views.pages.transactions.form :as edit]
            [auto-ap.views.pages.transactions.manual :as manual]
            [auto-ap.views.pages.transactions.side-bar :as side-bar]
            [auto-ap.views.pages.transactions.table :as table]
            [auto-ap.views.utils :refer [dispatch-event with-user]]
            [clojure.set :as set]
            [re-frame.core :as re-frame]
            [reagent.core :as reagent]
            [vimsical.re-frame.fx.track :as track]
            [auto-ap.status :as status]))



(defn data-params->query-params [params]
  {:start (:start params 0)
   :per-page (:per-page params)
   :sort (:sort params)
   :client-id (:id @(re-frame/subscribe [::subs/client]))
   :vendor-id (:id (:vendor params))
   :date-range (:date-range params)
   :account-id (:id (:account params))
   :bank-account-id (:id (:bank-account params))
   :amount-gte (:amount-gte (:amount-range params))
   :exact-match-id (some-> (:exact-match-id params) str)
   :unresolved (:unresolved params)
   :location (:location params)
   :import-batch-id (some-> (:import-batch-id params) str)
   :amount-lte (:amount-lte (:amount-range params))
   :description (:description params)
   :approval-status (condp = @(re-frame/subscribe [::subs/active-page])
                      :transactions nil
                      :unapproved-transactions :unapproved
                      :requires-feedback-transactions :requires-feedback
                      :excluded-transactions :excluded
                      :approved-transactions :approved)})

(re-frame/reg-event-fx
 ::params-change
 [with-user]
 (fn [{:keys [user db ]} [_ params]]
   (try 
     {:graphql {:token user
                :owns-state {:single [::data-page/page ::page]}
                :query-obj {:venia/queries [{:query/data  [:transaction_page
                                                           {:filters (data-params->query-params params)}
                                                           [[:data transaction-read]
                                                            :total
                                                            :start
                                                            :end]]
                                             :query/alias :result}]} 
                :on-success (fn [result]
                              
                              
                              [::data-page/received ::page (:result result)])}}
     (catch js/Error e
       ;; this catches an error where you choose a parameter, change to invoices page, then change to voided invoices
       (println "Error!" e)))))

(re-frame/reg-event-fx
 ::bulk-change-transaction-status
 (fn [cofx [_ status params]]
   (let [checked @(re-frame/subscribe [::data-page/checked ::page])
         checked-params (get checked "header")
         specific-transactions (map :id (vals (dissoc checked "header")))]
     (println checked-params)
     {:db (-> (:db cofx)
              (assoc-in [:status :loading] true))
      :graphql {:token (-> cofx :db :user)
                :owns-state {:single ::bulk-change-transaction-status}
                :query-obj
                {:venia/operation {:operation/type :mutation
                                   :operation/name "BulkChangeTransactionStatus"}
                 :venia/queries [{:query/data
                                  [:bulk-change-transaction-status
                                   {:filters (some-> checked-params data-params->query-params)
                                    :status status
                                    :ids specific-transactions}
                                   [:message]]}]}
                :on-success (fn [result]
                              [::params-change params])}})))

(re-frame/reg-event-fx
 ::delete-selected
 (fn [cofx [_ params]]
   (let [checked @(re-frame/subscribe [::data-page/checked ::page])
         checked-params (get checked "header")
         specific-transactions (map :id (vals (dissoc checked "header")))]
     (println checked-params)
     {:db (-> (:db cofx)
              (assoc-in [:status :loading] true))
      :graphql {:token (-> cofx :db :user)
                :owns-state {:single ::delete-selected}
                :query-obj
                {:venia/operation {:operation/type :mutation
                                   :operation/name "DeleteTransactions"}
                 :venia/queries [{:query/data
                                  [:delete-transactions
                                   {:filters (some-> checked-params data-params->query-params)
                                    :ids specific-transactions}
                                   [:message]]}]}
                :on-success (fn [result]
                              [::params-change params])}})))

(re-frame/reg-event-fx
 ::unmounted
 (fn [{:keys [db]} _]
   {:dispatch-n [[::data-page/dispose ::page]
                 [::status/dispose-single ::manual-import]]
    ::track/dispose {:id ::params}
    ::forward/dispose [{:id ::updated}
                       {:id ::manual-import}]}))

(re-frame/reg-event-fx
 ::mounted
 (fn [{:keys [db]} _]
   {::track/register {:id ::params
                      :subscription [::data-page/params ::page]
                      :event-fn (fn [params]
                                  [::params-change params])}
    ::forward/register [{:id ::updated
                         :events #{::edit/edited}
                         :event-fn (fn [[_ edited-transaction]]
                                     [::data-page/updated-entity ::page edited-transaction])}
                        {:id ::manual-import
                         :events #{::manual/import-completed}
                         :event-fn (fn [[_ {:keys [imported errors] :as result}]]
                                     [::status/info ::manual-import (str "Successfully imported " imported " transactions"

                                                                         (when (seq errors)
                                                                           (str 
                                                                            ", " (count errors) " errors. "
                                                                            "Example: '" (str  (:info (first (:errors (first errors))))) "'")))])}]}))


(defn content []
  (let [is-admin? @(re-frame/subscribe [::subs/is-admin?])
        params @(re-frame/subscribe [::data-page/params ::page])
        checked @(re-frame/subscribe [::data-page/checked ::page])]
    [:div 
     [:h1.title "Transactions"]
     [status/status-notification {:statuses [[::status/single ::bulk-change-transaction-status]
                                             [::status/single ::delete-selected]
                                             [::status/single ::manual-import]]}]
     (when is-admin?
       [:div.is-pulled-right
        [:div.buttons 
         
         (into [:div.tags ] (map (fn [[z {:keys [id]}]]
                                   (if (= "header" z)
                                     [:span.tag.is-medium {:on-click
                                                           (dispatch-event [::data-page/remove-check ::page "header"])}
                                      "All visible transactions"]
                                     [:span.tag.is-medium id
                                      [:button.delete.is-small {:on-click
                                                                (dispatch-event [::data-page/remove-check ::page id])}]]))
                                 checked))
         [:button.button.is-outlined.is-primary {:on-click (dispatch-event [::manual/opening])}
          "Manual Yodlee Import"]
         [:button.button.is-warning {:on-click (dispatch-event [::bulk-change-transaction-status :unapproved params])
                                     :class (status/class-for @(re-frame/subscribe [::status/single ::bulk-change-transaction-status]))
                                     :disabled (or (status/disabled-for @(re-frame/subscribe [::status/single ::bulk-change-transaction-status]))
                                                   (not (seq checked)))}
          "Unapprove selected"]

         [:button.button.is-warning {:on-click (dispatch-event [::bulk-change-transaction-status :excluded params])
                                     :class (status/class-for @(re-frame/subscribe [::status/single ::bulk-change-transaction-status]))
                                     :disabled (or (status/disabled-for @(re-frame/subscribe [::status/single ::bulk-change-transaction-status]))
                                                   (not (seq checked)))}
          "Exclude selected"]
         [:button.button.is-warning {:on-click (dispatch-event [::bulk-change-transaction-status :requires-feedback params])
                                     :class (status/class-for @(re-frame/subscribe [::status/single ::bulk-change-transaction-status]))
                                     :disabled (or (status/disabled-for @(re-frame/subscribe [::status/single ::bulk-change-transaction-status]))
                                                   (not (seq checked)))}
          "Client Review"]
         [:button.button.is-danger {:on-click (dispatch-event [::delete-selected params])
                                    :class (status/class-for @(re-frame/subscribe [::status/single ::delete-selected]))
                                    :disabled (or (status/disabled-for @(re-frame/subscribe [::status/single ::delete-selected]))
                                                  (not (seq checked)))}
          "Delete selected"]]])
     [table/table {:id :transactions
                   :check-boxes? is-admin?
                   :data-page ::page}]]))


(defn transactions-page [{:keys [approval-status]}]
  (reagent/create-class
   {:display-name "transaction-page"
    :component-will-unmount #(re-frame/dispatch [::unmounted])
    :component-did-mount #(re-frame/dispatch [::mounted])
    :reagent-render
    (fn []
      (let [{transaction-bar-active? :active?} @(re-frame/subscribe [::forms/form ::edit/form])]
        [side-bar-layout
         {:side-bar [side-bar/side-bar {:data-page ::page}]
          :main [:div ^{:key approval-status}
                 [content]]
          :right-side-bar [appearing-side-bar
                           {:visible? transaction-bar-active?}
                           [edit/form]]}]))}))

