(ns auto-ap.views.pages.transactions.bulk-updates
  (:require
   [auto-ap.forms :as forms]
   [auto-ap.status :as status]
   [auto-ap.subs :as subs]
   [auto-ap.views.components.expense-accounts-field
    :as expense-accounts-field
    :refer [expense-accounts-field-v2]]
   [auto-ap.views.components.modal :as modal]
   [auto-ap.views.pages.data-page :as data-page]
   [auto-ap.views.pages.transactions.common
    :refer [data-params->query-params]]
   [auto-ap.views.utils :refer [dispatch-event with-user]]
   [clojure.string :as str]
   [re-frame.core :as re-frame]
   [reagent.core :as r]
   [vimsical.re-frame.fx.track :as track]
   [auto-ap.events :as events]
   [vimsical.re-frame.cofx.inject :as inject]
   [auto-ap.forms.builder :as form-builder]
   [auto-ap.views.components :as com]))

(re-frame/reg-event-fx
  ::coded
  (fn [_ [_ _ _]]
    {:dispatch-n [[::modal/modal-closed]
                  [:auto-ap.views.pages.transactions/params-change
                   @(re-frame/subscribe [::data-page/params :auto-ap.views.pages.transactions/page])]
                  [::data-page/reset-checked :auto-ap.views.pages.transactions/page]]}))

(re-frame/reg-event-fx
 ::code-selected
 [with-user (forms/in-form ::form) (re-frame/inject-cofx ::inject/sub [::subs/client])]
 (fn [{:keys [user db] ::subs/keys [client]} [_ checked]]
   (let [checked-params        (get checked "header")
         specific-transactions (map :id (vals (dissoc checked "header")))
         data (:data db)]
     {:graphql
      {:token      user
       :owns-state {:single ::form}
       :query-obj  {:venia/operation {:operation/type :mutation
                                      :operation/name "BulkCodeTransactions"}
                    :venia/queries   [[:bulk-code-transactions
                                       {:filters (some-> checked-params data-params->query-params)
                                        :ids specific-transactions
                                        :vendor (:id (:vendor data))
                                        :approval-status (:transaction-approval-status data)
                                        :accounts (map
                                                    #(-> %
                                                         (update :id (fn [i] (if (some-> i (str/starts-with? "new-"))
                                                                               nil
                                                                               i)))
                                                         (assoc :percentage (/ (get-in % [:amount-percentage]) 100 ))
                                                         (assoc :account-id (get-in % [:account :id]))
                                                         (select-keys [:percentage :id :location :account-id]))
                                                    (:accounts data))}
                                       [:message]
                                     ]]}
       :on-success (fn [result]
                     [::coded
                      (:message result)
                      checked-params
                      ])}})))

(re-frame/reg-event-db
  ::changed
  (forms/change-handler ::form
                        (fn  [data field value]
                          (cond  (and (= [:vendor-preferences] field)
                                      value)
                                 [[:accounts] (expense-accounts-field/default-account (:accounts data)
                                                                                      (:default-account value)
                                                                                      (:total data)
                                                                                      [])]
                                 :else
                                 []))))

(re-frame/reg-event-fx
  ::changed-vendor
  [(forms/in-form ::form)]
  (fn [{{{:keys [client]} :data} :db} [_ vendor]]
    (when (and (:id client) (:id vendor))
      {:dispatch [::events/vendor-preferences-requested {:client-id  (:id client)
                                                         :vendor-id  (:id vendor)
                                                         :on-success [::changed [:vendor-preferences]]
                                                         :on-failure [:hello]}]})))

(re-frame/reg-event-fx
  ::mounted
  (fn []
    {::track/register {:id           ::vendor-change
                       :subscription [::forms/field ::form [:vendor]]
                       :event-fn     (fn [v]
                                       [::changed-vendor v])}}))

(re-frame/reg-event-fx
  ::unmounted
  (fn []
    {::track/dispose {:id ::vendor-change}}))


(defn form-content [_]
  (let [{:keys [data]} @(re-frame/subscribe [::forms/form ::form])]
    [form-builder/builder {:submit-event [::code-selected]
                        :change-event [::changed]
                        :id           ::form}

     
     [form-builder/field-v2 {:field :vendor}
      "Vendor"
      [com/search-backed-typeahead {:search-query (fn [i]
                                                    [:search_vendor
                                                     {:query i}
                                                     [:name :id]])
                                    :auto-focus   true}]]

     [form-builder/field-v2 {:field   [:transaction-approval-status]}
      "Approval Status"
      [com/button-radio-input
       {:options [[:unapproved "Unapproved"]
                  [:requires-feedback "Client Review"]
                  [:approved "Approved"]
                  [:excluded "Excluded from Ledger"]]}]]

     [form-builder/raw-field-v2 {:field :accounts}
      [expense-accounts-field-v2 {:descriptor       "account asssignment"
                                  :percentage-only? true
                                  :client           (:client data)
                                  :locations        (into ["Shared"] @(re-frame/subscribe [::subs/locations-for-client (:id (:client data))]))
                                  :max              100}]]]))
(defn form [_]
  (r/create-class
    {:display-name           "transaction-bulk-update-form"
     :component-did-mount    #(re-frame/dispatch [::mounted])
     :component-will-unmount #(re-frame/dispatch [::unmounted])
     :reagent-render         (fn [p]
                               [form-content p])}))

(re-frame/reg-event-fx
  ::code-requested
  (fn [{:keys [db]} [_ checked params total-visible]]
    (let [to-delete (if (get checked "header")
                      [:b.strong.has-text-danger "all " total-visible " visible transactions"]
                      (str (count checked) " transactions"))]
      {:dispatch [::modal/modal-requested {:title       "Confirmation"
                                           :body        [:div "Please fill in the details on how to code " to-delete ":"
                                                         [form ]]
                                           :cancel?     true
                                           :confirm     {:value       "Code"
                                                         :class       "is-danger"
                                                         :status-from [::status/single ::form]
                                                         :on-click    (dispatch-event [::code-selected checked] )}
                                           :close-event [::status/completed ::code-selected]}]
       :db (-> db
               (forms/start-form ::form {:accounts [{:amount-percentage 100.0 }]
                                         :client @(re-frame/subscribe [::subs/client (:client-id params)])}))})))
