(ns auto-ap.views.pages.admin.users.form
  (:require
   [auto-ap.forms :as forms]
   [auto-ap.forms.builder :as form-builder]
   [auto-ap.schema :as schema]
   [auto-ap.status :as status]
   [auto-ap.subs :as subs]
   [auto-ap.views.components :as com]
   [auto-ap.views.components.modal :as modal]
   [auto-ap.views.utils :refer [dispatch-event with-user]]
   [malli.core :as m]
   [re-frame.core :as re-frame]))

(def client-schema
  (m/schema [:map [:client schema/reference]]))

(def user-schema
  (m/schema
    [:map
     [:name schema/not-empty-string]
     [:role [:enum :none :user :manager :power_user :admin]]
     [:clients  {:optional true}
      [:maybe 
       [:sequential client-schema]]]]))

(re-frame/reg-event-fx
 ::saving
 [with-user (forms/in-form ::form)]
 (fn [{:keys [db user]} [_]]
   (if (m/validate user-schema (:data db))
     {:graphql
      {:token      user
       :owns-state {:single ::form}
       :query-obj  {:venia/operation {:operation/type :mutation
                                      :operation/name "EditUser"}
                    :venia/queries   [{:query/data [:edit-user
                                                    {:edit-user (-> (:data db)
                                                                    (update :clients #(map (comp :id :client) %))
                                                                    (select-keys #{:id :name :clients :role}))}
                                                    [:id :name :role [:clients [:id :name]]]]}]}  
       :on-success [::saved]}}

     {:dispatch-n [[::forms/attempted-submit ::form]
                   [::status/error ::form [{:message "Please fix the errors and try again."}]]]})
   ))

(re-frame/reg-event-fx
 ::saved
 (forms/triggers-stop ::form)
 (fn [_ _]
   {:dispatch [::modal/modal-closed]}))





(defn form []
  (let [{:keys [data]} @(re-frame/subscribe [::forms/form ::form])
        clients @(re-frame/subscribe [::subs/clients])]
    [:<>
     [form-builder/builder {:submit-event [::saving]
                            :id           ::form
                            :schema user-schema}
      [form-builder/field-v2 {:required? true
                             :field :name}
       "Name"
       [:input.input {:type  "text"}]]
      [form-builder/field-v2 {:required? true
                              :field :role}
       "Role"
       [com/select-field {:options [[:none "None"]
                                    [:user "User"]
                                    [:manager "Manager"]
                                    [:power_user "Power User"]
                                    [:admin "Admin"]]
                          :allow-nil? false
                          :keywordize? true}]]
      (when (#{:user :manager :power_user} (:role data))
        [form-builder/field-v2 {:field    :clients}
         "Client"
         [com/multi-field-v2 {:template [[form-builder/raw-field-v2 {:field :client}
                                          [com/entity-typeahead
                                           {:entities     clients
                                            :entity->text :name
                                            :style        {:width "13em"}}]]]
                              :key-fn :id
                              :schema [:sequential client-schema]
                              :new-text "Grant access to client"}]])
      
      [form-builder/hidden-submit-button]]]))

(re-frame/reg-event-fx
 ::editing
 (fn [{:keys [db]} [_ d]]
   {:db       (-> db
                  (forms/start-form ::form (update d :clients #(mapv (fn [x] {:client x :id (random-uuid)}) %))))
    :dispatch [::modal/modal-requested {:title   (str "Edit user " (:name d))
                                        :body    [form]
                                        :cancel? false
                                        :confirm {:value       "Save"
                                                  :status-from [::status/single ::form]
                                                  :class       "is-primary"
                                                  :on-click    (dispatch-event [::saving])
                                                  :close-event [::status/completed ::form]}}]}))
