(ns auto-ap.views.pages.admin.accounts.form
  (:require
   [auto-ap.forms :as forms]
   [auto-ap.forms.builder :as form-builder]
   [auto-ap.schema :as schema]
   [auto-ap.subs :as subs]
   [auto-ap.views.components :as com]
   [auto-ap.views.components.layouts :refer [side-bar]]
   [auto-ap.views.components.typeahead :refer [typeahead-v3]]
   [auto-ap.views.utils :refer [dispatch-event with-user]]
   [clojure.string :as str]
   [malli.core :as m]
   [re-frame.core :as re-frame]
   [vimsical.re-frame.cofx.inject :as inject]))

(def types [:dividend :expense :asset :liability :equity :revenue])
(def applicabilities [:global :optional :customized])
(def allowances [:allowed :denied :warn :admin-only])

(re-frame/reg-sub
 ::request
 :<- [::forms/form ::form]
 (fn [{{:keys [id location type client-overrides applicability invoice-allowance vendor-allowance numeric-code name account-set]} :data}]
   {:id id
    :type (keyword type)
    :applicability (keyword applicability)
    :invoice-allowance (keyword invoice-allowance)
    :vendor-allowance (keyword vendor-allowance)
    :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-event-db
 ::editing
 (fn [db [_ which complete-listener]]
   (-> db
       (forms/start-form ::form which complete-listener))))

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


(re-frame/reg-event-fx
 ::saving
 [with-user (re-frame/inject-cofx ::inject/sub [::request]) ]
 (fn [{:keys [user] ::keys [request]} _]
   (let [_ @(re-frame/subscribe [::forms/form ::form])]
     {:graphql
      {:owns-state {:single ::form}
       :token      user
       :query-obj  {:venia/operation {:operation/type :mutation
                                      :operation/name "UpsertAccount"}
                    :venia/queries   [{:query/data [:upsert-account
                                                    {:account request}
                                                    [:id :type :name :account-set :numeric-code :location :applicability :invoice-allowance :vendor-allowance [:client-overrides [:name :id [:client [:id :name]]]]]]}]}
       :on-success [::edited]
       :on-error   [::forms/save-error ::form]}})))

(def account-customization-schema
  (m/schema
    [:map [:client schema/reference]
     [:name schema/not-empty-string]]))

(def account-schema
  (m/schema 
    [:map
     [:numeric-code schema/integer-code]
     [:name schema/not-empty-string]
     [:type [:enum :dividend :expense :asset :liability :equity :revenue]]
     [:location {:optional true} [:maybe :string]]
     [:applicability [:enum :global :optional :customized]]
     [:invoice-allowance [:enum :allowed :denied :warn :admin-only]]
     [:vendor-allowance [:enum :allowed :denied :warn :admin-only]]
     [:client-overrides {:optional true}
      [:maybe [:sequential account-customization-schema]]]]))

(defn form [_]
  (let [{account :data } @(re-frame/subscribe [::forms/form ::form])] 
    [side-bar {:on-close (dispatch-event [::forms/form-closing ::form])}
     [form-builder/builder {:change-event [::forms/change ::form]
                            :submit-event [::saving]
                            :id           ::form
                            :schema account-schema}
      [form-builder/section {:title (if (:id account)
                                      "Edit account"
                                      "Add account")}
       [form-builder/field-v2 {:field :numeric-code}
        "Code"
        [com/number-input 
         {:disabled (boolean (:id account))
          :auto-focus (not (boolean (:id account))) 
          :style {:width "9em"}}]]

       [form-builder/field-v2 {:field :name}
        "Name"
        [:input.input {:type  "text"
                       :auto-focus (boolean (:id account))}]]

       [form-builder/field-v2 {:field :type}
        "Account Type"
        [com/select-field {:options    (map (fn [l]
                                              [l (str/capitalize (name l))])
                                         types)
                           :allow-nil? true
                           :keywordize? true}]]


       [form-builder/field-v2 {:field :location}
        "Location"
        [:input.input.known-field.location {:type  "text"}]]

       [form-builder/field-v2 {:field :invoice-allowance}
        "Invoice Allowance"
        [com/select-field {:options     (map (fn [l]
                                              [l
                                               (str/capitalize (name l))])
                                            allowances)
                           :allow-nil?  true
                           :keywordize? true}]]

       [form-builder/field-v2 {:field :vendor-allowance}
        "Vendor Allowance"
        [com/select-field {:options     (map (fn [l]
                                               [l
                                                (str/capitalize (name l))])
                                             allowances)
                           :allow-nil?  true
                           :keywordize? true}]]

       [form-builder/section {:title "Client"}
        [:h2.subtitle "Client"]
        [form-builder/field-v2 {:field :applicability}
         "Applicability"
         [com/select-field {:options    (map (fn [l]
                                               [l
                                                (str/capitalize (name l))])
                                          applicabilities)
                            :allow-nil? true
                            :keywordize? true}]]
        [form-builder/field-v2 {:field :client-overrides}
         "Customizations"
         [com/multi-field-v2 {:template [[form-builder/raw-field-v2 {:field :client}
                                          [typeahead-v3 {:entities     @(re-frame/subscribe [::subs/clients])
                                                         :style        {:width "13em"}
                                                         :entity->text :name}]]
                                         [form-builder/raw-field-v2 {:field :name}
                                          [:input.input {:type        "text"
                                                         :style       {:width "15em"}
                                                         :placeholder "Bubblegum"}]]]
                              :key-fn :id
                              :schema [:sequential account-customization-schema]}]]]
       [form-builder/error-notification]

       [form-builder/submit-button "Save"]]]]))
