(ns auto-ap.views.pages.admin.users
  (:require-macros [cljs.core.async.macros :refer [go]])
  (:require [re-frame.core :as re-frame]
            [reagent.core :as reagent]
            [clojure.string :as str]
            [auto-ap.subs :as subs]
            [auto-ap.events :as events]
            [auto-ap.entities.companies :as entity]
            [auto-ap.views.components.address :refer [address-field]]
            [auto-ap.views.utils :refer [login-url dispatch-value-change bind-field horizontal-field dispatch-event]]
            [auto-ap.views.components.modal :refer [modal action-modal]]
            [auto-ap.utils :refer [by replace-if]]
            [cljs.reader :as edn]
            [auto-ap.routes :as routes]
            [bidi.bidi :as bidi]))

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

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

(re-frame/reg-event-fx
 ::users-mounted
 (fn [{:keys [db]} _]
   {:graphql {:token (:user db)
              :query-obj {:venia/queries [[:user
                                           [:name
                                            :id
                                            :role
                                            [:companies [:id :name]]]]]} 
              :on-success [::received]}}))

(re-frame/reg-event-db
 ::change
 (fn  [db [_ path value]]
   (assoc-in db (concat [::editing] path)
             value)))

(re-frame/reg-event-db
 ::received
 (fn [db [_ d]]
   (assoc-in db [::users] (:user d))))

(re-frame/reg-event-db
 ::edit
 (fn [db [_ d]]
   (re-frame/dispatch [::events/modal-status ::edit-user {:visible? true}])
   (if-let [user (get (by :id (::users db)) d)]
     (assoc-in db [::editing :user] user)
     (dissoc db ::editing))))

(re-frame/reg-event-db
 ::add-company
 (fn [db [_ d]]
   (let [company (get @(re-frame/subscribe [::subs/companies-by-id])
                         (js/parseInt (get-in db [::editing :adding-company])))]
     (update-in db [::editing :user :companies] conj company))))

(re-frame/reg-event-db
 ::remove-company
 (fn [db [_ d]]
   (update-in db [::editing :user :companies] #(filter (fn [c] (not= (:id c) d)) %))))

(re-frame/reg-event-fx
 ::save
 (fn [{:keys [db]} [_]]
   {:db (-> db
            (assoc-in [::editing :saving?] true ))
    :graphql
    {:token (-> db :user)
     
     :query-obj {:venia/operation {:operation/type :mutation
                                   :operation/name "EditUser"}
                 
                 :venia/queries [{:query/data [:edit-user
                                               {:edit-user (update (get-in db [::editing :user]) :companies #(map :id %))}
                                               [:id :name :role [:companies [:id :name]]]]}]}  
     :on-success [::saved]}}))

(re-frame/reg-event-fx
 ::saved
 (fn [{:keys [db]} [_ {:keys [edit-user]}]]
   (re-frame/dispatch [::events/modal-completed ::edit-user])
   {:db (-> db
            (assoc-in [::editing :saving?] false )
            (dissoc ::editing)
            (update ::users
                    (fn [us]
                      (replace-if #(= (:id %1) (:id %2)) edit-user us) 
                      )))}))

(defn users-table []
  (let [users (re-frame/subscribe [::users])]
    [:table {:class "table", :style {:width "100%"}}
     [:thead  
      [:tr  
       [:th "User"]
       [:th "Role"]
       [:th "Companies"]]]
     [:tbody (for [{:keys [id name role companies] :as c} @users]
               ^{:key (str name "-" id )}
               [:tr {:on-click (fn [] (re-frame/dispatch [::edit id]))
                     :style {"cursor" "pointer"}}
                [:td name]
                [:td role]
                [:td (str/join ", " (map :name companies))]])]]))



(def admin-users-page
  (with-meta
    (fn []
      [:div
       (let [companies (re-frame/subscribe [::users])
             editing @(re-frame/subscribe [::editing])]
         [:div
          [:h1.title "Users"]
          [users-table]
          
          [action-modal {:title (str "Edit " (:name (:user editing)))
                         :id ::edit-user
                         :action-text "Save"
                         :save-event [::save]}
           [horizontal-field
            [:label.label  "Name"]
            [bind-field
             [:input.input {:type "text"
                            :field [:user :name]
                            :spec ::entity/name
                            :event ::change
                            :subscription editing}]]]

           [horizontal-field
            [:label.label  "Role"]
            [:div.control
             [:div.select
              [bind-field
               [:select {:type "select"
                         :field [:user :role]
                         :spec ::entity/name
                         :event ::change
                         :subscription editing}
                [:option {:value "none"} "None"]
                [:option {:value "user"} "User"]
                [:option {:value "admin"} "Admin"]]]]]]
           

           (when (= "user" (:role (:user editing)))
             [horizontal-field
              [:label.label "Companies"]
              [:div.control

               [:div.field.has-addons
                [:p.control
                 [:div.select
                  [bind-field
                   [:select {:type "select"
                             :field [:adding-company]
                             :event ::change
                             :subscription editing}
                    [:option]
                    (let [used-companies (set (map :id (:companies (:user editing))))]
                      (for [{:keys [id name]} @(re-frame/subscribe [::subs/companies])
                            :when (not (used-companies id))]
                        ^{:key id} [:option {:value id} name]))]]]]
                [:p.control
                 [:button.button.is-primary {:on-click (dispatch-event [::add-company])} "Add"]]]
               
               [:ul
                (for [{:keys [id name]} (:companies (:user editing))]
                  ^{:key id} [:li  name [:a.icon {:on-click (dispatch-event [::remove-company id])} [:i.fa.fa-times ]]])]]])]])])
    {:component-will-mount #(re-frame/dispatch-sync [::users-mounted {}]) }))


