(ns auto-ap.views.pages.admin.accounts.form
  (:require [auto-ap.entities.account :as entity]
            [auto-ap.forms :as forms]
            [auto-ap.subs :as subs]
            [auto-ap.views.components.layouts :refer [side-bar]]
            [auto-ap.views.components.typeahead :refer [typeahead-v3]]
            [auto-ap.views.utils :refer [dispatch-event multi-field]]
            [clojure.spec.alpha :as s]
            [clojure.string :as str]
            [re-frame.core :as re-frame]))

(def types [:dividend :expense :asset :liability :equity :revenue])
(def applicabilities [:global :optional :customized])



(re-frame/reg-sub
 ::request
 :<- [::forms/form ::form]
 (fn [{{:keys [id location type client-overrides applicability numeric-code name account-set]} :data}]
   {:id id
    :type (keyword type)
    :applicability (keyword applicability)
    :location (if (clojure.string/blank? location)
                nil
                location)
    :numeric-code (js/parseInt numeric-code)
    :name name
    :account-set account-set
    :client-overrides (map (fn [client-override]
                             {:id (:id client-override)
                              :client-id (:id (:client client-override))
                              :name (if (str/blank?  (:name client-override))
                                      nil
                                      (:name client-override))})
                           client-overrides)}))

(re-frame/reg-sub
 ::can-submit
 :<- [::request]
 (fn [request]
   (s/valid? ::entity/account request)))

(re-frame/reg-event-db
 ::editing
 (fn [db [_ which complete-listener]]
   (println "WHICH" which)
   (-> db
       (forms/start-form ::form which complete-listener))))

(re-frame/reg-event-fx
 ::edited
 [(forms/triggers-saved ::form :upsert-account)]
 (fn [{:keys [db]} [_ {:keys [upsert-account]}]]))

(re-frame/reg-event-db
 ::add-client-override
 [(forms/in-form ::form)]
 (fn [form]
   (update form :data (fn [data]
                        (-> data
                            (update :client-overrides conj (:new-client-override data))
                            (dissoc :new-client-override))))))

(re-frame/reg-event-fx
 ::saving
 (fn [{:keys [db]} _]
   (when @(re-frame/subscribe [::can-submit]) 
     (let [{{:keys [id type name numeric-code account-set]} :data :as data} @(re-frame/subscribe [::forms/form ::form])]
       {:db (forms/loading db ::form )
        :graphql
        {:token (-> db :user)
         :query-obj {:venia/operation {:operation/type :mutation
                                       :operation/name "UpsertAccount"}
                     :venia/queries [{:query/data [:upsert-account
                                                   {:account @(re-frame/subscribe [::request])}
                                                   [:id :type :name :account-set :numeric-code :location :applicability [:client-overrides [:name :id [:client [:id :name]]]]]]}]}
         :on-success [::edited]
         :on-error [::forms/save-error ::form]}}))))

(def account-form (forms/vertical-form {:can-submit [::can-submit]
                                        :change-event [::forms/change ::form]
                                        :submit-event [::saving]
                                        :id ::form}))

(defn form [_]
  (let [{error :error account :data } @(re-frame/subscribe [::forms/form ::form])
        {:keys [form-inline field field-holder raw-field error-notification submit-button]} account-form] 
    
    ^{:key (:id account)}
    [side-bar {:on-close (dispatch-event [::forms/form-closing ::form])}
     (form-inline {:title (if (:id account)
                            "Edit account"
                            "Add account")}
                  [:<>

                   (field "Account Set"
                          [:input.input {:type "text"
                                         :field :account-set
                                         :disabled (boolean (:id account))
                                         :spec ::entity/account-set}])

                   (field "Code"
                          [:input.input {:type "text"
                                         :field :numeric-code
                                         :disabled (boolean (:id account))
                                         :spec ::entity/numeric-code}])

                   (field "Name"
                          [:input.input {:type "text"
                                         :field :name
                                         :spec ::entity/name}])

                   (field-holder "Account Type"
                                 [:div.select
                                  (raw-field
                                   [:select {:type "select"
                                             :field :type
                                             :spec (set types)}
                                    (map (fn [l]
                                           [:option {:value (name l)} (str/capitalize (name l))]) types)])])


                   (field "Location"
                          [:input.input.known-field.location {:type "text"
                                                              :field :location
                                                              :spec ::entity/location}])

                   [:h2.subtitle "Client"]
                   (field-holder "Applicability"
                                 [:div.select
                                  (raw-field
                                   [:select {:type "select"
                                             :field :applicability
                                             :spec (set applicabilities)}
                                    (map (fn [l]
                                           [:option {:value (name l)} (str/capitalize (name l))]) applicabilities)])])
                   (field "Customizations"
                          [multi-field {:type "multi-field"
                                        :field [:client-overrides]
                                        :template [[typeahead-v3 {:entities @(re-frame/subscribe [::subs/clients])
                                                                  :style {:width "20em"}
                                                                  :entity->text :name
                                                                  :type "typeahead-v3"
                                                                  :field [:client]}]
                                                   [:input.input {:type "text"
                                                                  :style {:width "20em"}
                                                                  :placeholder "Bubblegum"
                                                                  :field [:name]}]
                                                   ]}])
                   (error-notification)

                   (submit-button "Save")])]))
