(ns auto-ap.events.admin.vendors
  (:require [re-frame.core :as re-frame]
            [clojure.spec.alpha :as s]
            [auto-ap.db :as db]
            [auto-ap.routes :as routes]
            [auto-ap.effects :as effects]
            [auto-ap.entities.vendors :as entity]
            [auto-ap.events :as events]
            [auto-ap.utils :refer [by]]

            [bidi.bidi :as bidi]))

(def vendor-query
  [:id :name :default-expense-account
   [:primary-contact [:name :phone :email :id]]
   [:secondary-contact [:id :name :phone :email]]
   :print-as :invoice-reminder-schedule :code
   [:address [:street1 :street2 :city :state :zip]]])

(re-frame/reg-event-fx
 ::edit
 (fn  [{:keys [db]} [_ vendor-id]]
   {:db (assoc-in db [:admin :vendor]
                  (get  (:vendors db) vendor-id))
    :dispatch [::events/modal-status :auto-ap.views.pages.admin.vendors/admin-vendor {:visible? true}]}))

(re-frame/reg-event-fx
 ::new
 (fn  [{:keys [db]} _]
   {:db (assoc-in db [:admin :vendor]
                  {})
   :dispatch [::events/modal-status :auto-ap.views.pages.admin.vendors/admin-vendor {:visible? true}]}))

(re-frame/reg-event-fx
 ::save
 (fn  [{:keys [db]} _]
   (let [edited-vendor (get-in db [:admin :vendor])
         fx {:db (assoc-in db [:admin :vendor :saving?] true)}]
     (when (s/valid? ::entity/vendor edited-vendor)
       (assoc fx :graphql
              {:token (-> db :user)
               :query-obj {:venia/operation {:operation/type :mutation
                                             :operation/name "UpsertVendor"}
                           
                           :venia/queries [{:query/data [:upsert-vendor
                                                         {:vendor edited-vendor}
                                                         vendor-query]}]}  
               :on-success [::save-complete]
               :on-error [::save-error]})))))

(re-frame/reg-event-fx
 ::remind
 (fn  [{:keys [db] :as fx} [_ id]]
   { :http {:method :post
            :token (:user db)
            :headers {"Content-Type" "application/edn"}
            :uri (str "/api/vendors/" id "/remind")
            :on-success [::reminder-sent]
            :on-error [::failed "Failed to send reminder"]}
    :db (assoc-in db [:admin :banner] nil)}))

(re-frame/reg-event-db
 ::reminder-sent
 (fn  [db [_ error]]
   (-> db
       (assoc-in [:admin :banner] "Reminder sent!"))))

(re-frame/reg-event-db
 ::failed
 (fn  [db [_ error]]
   (-> db
       (assoc-in [:admin :banner] error))))

(re-frame/reg-event-fx
 ::save-complete
 (fn  [{:keys [db]} [_ {vendor :upsert-vendor} ]]
   {:dispatch [::events/modal-completed :auto-ap.views.pages.admin.vendors/admin-vendor ]
    :db (-> db
            
            (assoc-in [:admin :vendor] nil)
            (assoc-in [:vendors (:id vendor)] vendor))}))

(re-frame/reg-event-db
 ::save-error
 (fn  [db [_ vendor]]
   (-> db
       (assoc-in [:admin :vendor :error] true)
       (assoc-in [:admin :vendor :saving?] false))))

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

(re-frame/reg-event-db
 ::add-relationship
 (fn  [db [_ ]]
   (-> db
       (update-in [:admin :vendor :relationships] #(conj (or % [])
                                                         {:account-number (get-in db [:admin :vendor :new-relationship-account-number])
                                                          :client-id (get-in db [:admin :vendor :new-relationship-client])}))
       (update-in [:admin :vendor] dissoc :new-relationship-account-number :new-relationship-client))))

(re-frame/reg-event-db
 ::remove-relationship
 (fn  [db [_ i]]
   (-> db
       (update-in [:admin :vendor :relationships] #(vec (concat (subvec % 0 i) (subvec % (min (count %) (inc i)))))))))

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

(re-frame/reg-event-db
 ::received-vendors
 (fn  [db [_ vendors]]
   (assoc db :vendors (by :id (:vendor vendors )))))
