(ns auto-ap.views.pages.admin.rules.results-modal
  (:require [auto-ap.events :as events]
            [auto-ap.subs :as subs]
            [auto-ap.views.utils :refer [date->str dispatch-event with-user]]
            [auto-ap.views.pages.transactions.common :refer [transaction-read]]
            [re-frame.core :as re-frame]
            [auto-ap.views.components.modal :as modal]
            [auto-ap.status :as status]))



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

(re-frame/reg-sub
 ::runnable?
 (fn [db]
   (::runnable? db)))

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

(re-frame/reg-sub
 ::all-checked
 (fn [db]
   (::all-checked db nil)))

(re-frame/reg-sub
 ::checked-count
 :<- [::checked]
 (fn [checked]
   (if (seq checked)
     (count checked)
     0)))

(defn results-body [params]
  (let [runnable? @(re-frame/subscribe [::runnable?])
        checked @(re-frame/subscribe [::checked])
        all-checked @(re-frame/subscribe [::all-checked])
        checked-count @(re-frame/subscribe [::checked-count])]
    [:table.table.is-fullwidth.compact
     [:tr
      (when runnable?
        [:th {:style {:width "2em"}}
         [:input.checkbox {:type "checkbox"
                           :checked all-checked
                           :on-change (dispatch-event [::toggle-all])}]])
      [:th "Client"]
      [:th "Bank Account"]
      [:th "Description"]
      [:th "Date"]
      [:th "Amount"]]
     (for [{:keys [id client bank-account description-original date amount]} @(re-frame/subscribe [::test-results])]

       ^{:key id}
       [:tr
        (when runnable?
          [:td 
           [:input.checkbox {:type "checkbox"
                             :checked (boolean (checked id))
                             :on-change (dispatch-event [::toggle id])}]])
        [:td (:name client)]
        [:td (:name bank-account)]
        [:td description-original]
        [:td (when date (date->str date))]
        [:td amount]])]))

(defn foot [params]
  (let [runnable? @(re-frame/subscribe [::runnable?])
        checked @(re-frame/subscribe [::checked])
        all-checked @(re-frame/subscribe [::all-checked])
        checked-count @(re-frame/subscribe [::checked-count])
        status @(re-frame/subscribe [::status/single ::apply])]
    (when runnable?
      [:div 
       [:button.button.is-primary {:disabled (or (boolean (= checked-count 0))
                                                 (status/disabled-for status))
                                   :class (status/class-for status)
                                   :on-click (dispatch-event [::apply-rule params])}
        (str "Apply to " checked-count " transactions")]

       [:button.button.is-warning {:disabled (or (boolean (not all-checked))
                                                 (status/disabled-for status))
                                   :class (status/class-for status)
                                   :on-click (dispatch-event [::apply-rule (assoc params :all? true)])}
        (str "Apply to all transactions")]])))

(re-frame/reg-event-fx
 ::opening
 (fn [{:keys [db]} [_ results transaction-rule-id runnable?]]
   {:db (-> db
            (assoc ::all-checked false)
            (assoc ::test-results results)
            (assoc ::transaction-rule-id transaction-rule-id)
            (assoc ::checked #{})
            (assoc ::runnable? runnable?))
    :dispatch [::modal/modal-requested {:title "Rule results"
                                        :class "wide"
                                        :body [results-body]
                                        :status-from [::status/single ::apply]
                                        :foot [foot]}]}))

(re-frame/reg-event-db
 ::toggle
 [(re-frame/path [::checked])]
 (fn [checked [_ which]]
   (let [checked (or checked #{})]
     (if (checked which)
       (disj checked which)
       (conj checked which)))))

(re-frame/reg-event-db
 ::toggle-all
 (fn [db [_ which]]
   (let [{::keys [all-checked checked test-results]} db]
     (assoc db
            ::all-checked (not all-checked)
            ::checked (if all-checked
                       #{}
                       (into #{} (map :id test-results)))))))

(re-frame/reg-event-fx
 ::apply-rule
 [with-user]
 (fn [{:keys [db user]} [_ params]]
   {:graphql
    {:token user
     :owns-state {:single ::apply}
     :query-obj {:venia/operation {:operation/type :mutation
                                   :operation/name "MatchTransactionRules"}
                 :venia/queries [{:query/data [:match-transaction-rules
                                               {:transaction-ids (seq @(re-frame/subscribe [::checked]))
                                                :all (boolean (:all? params))
                                                :transaction-rule-id (::transaction-rule-id db)}
                                               transaction-read]}]}  
     :on-success [::modal/modal-closed]}}))
