(ns auto-ap.views.pages.admin.excel-import
  (:require
   [auto-ap.forms :as forms]
   [auto-ap.forms.builder :as form-builder]
   [auto-ap.schema :as schema]
   [auto-ap.views.components :as com]
   [auto-ap.shared-views.admin.side-bar :refer [admin-side-bar]]
   [auto-ap.views.components.layouts :refer [side-bar-layout]]
   [auto-ap.views.utils :refer [with-user]]
   [malli.core :as m]
   [re-frame.core :as re-frame]
   [reagent.core :as r]))

(re-frame/reg-event-fx
 ::save
 [ with-user (forms/in-form ::form)]
 (fn [{:keys [db user]}]
   {:http {:token      user
           :method     :post 
           :body       (pr-str {:excel-rows (:excel-rows (:data db))})
           :headers    {"Content-Type" "application/edn"}
           :uri        (str "/api/invoices/upload-integreat")
           :owns-state {:single ::form}
           :on-success [::save-complete]}}))

(re-frame/reg-event-fx
 ::save-complete
 (fn [{:keys [db]} [_ rows]]
   (cond-> 
       {:db (assoc db ::result rows)}
     (seq (:vendors-not-found rows)) (assoc :dispatch [::forms/start-form ::create-vendors  ]))))

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


(re-frame/reg-event-fx
 ::create-vendors
 [with-user  (forms/in-form ::create-vendors)]
 (fn [{:keys [user db]}]
   {:graphql {:token     user
              :owns-state {:single ::create-vendors}
              :query-obj {:venia/operation {:operation/type :mutation
                                            :operation/name "UpsertVendor"}
                          
                          :venia/queries
                          (for [[vendor-name {:keys [default-account]}] (:data db)]
                            {:query/data [:upsert-vendor
                                          {:vendor {:name vendor-name :default-account-id (:id default-account)}}
                                          [:id :name]]})}
              :on-success [::create-vendor-complete]}}))


(re-frame/reg-event-db
 ::create-vendor-complete
 (fn [db _]
   (dissoc db ::result )))

(def missing-vendor-schema
  (m/schema [:map-of :string
             [:map
              [:default-account schema/reference]]]))

(defn create-missing-vendors [{:keys [vendors]}]
  (let [{:keys [data]} @(re-frame/subscribe [::forms/form ::create-vendors])
        vendors-to-create (filter (fn [v] (:checked v))
                                  (vals data))]
    [form-builder/builder {:id           ::create-vendors
                           :submit-event [::create-vendors]
                           :schema missing-vendor-schema}
     [:article.message.is-warning.is-paddingless
      [:div.message-header
       "Some vendors could not be found"]

      [:div.message-body
       [:h2 "Check the vendors you want to create"]
       (for [v vendors]
         ^{:key v}
         [:div.field.is-grouped
          [:div.control 
           [form-builder/raw-field-v2 {:field [v :checked]}
            [com/checkbox {:label v}]]]

          [:div.control
           [form-builder/raw-field-v2 {:field [v :default-account]}
            [com/search-backed-typeahead {:search-query (fn [i]
                                                          [:search_account
                                                           {:query i}
                                                           [:name :id :location]])}]]]])
       [form-builder/error-notification]
       [form-builder/submit-button {:disabled (when-not (seq vendors-to-create) "disabled")}
        (str "Create " (count vendors-to-create) " vendors")]
       [:div.is-clearfix]]]]))

(defn admin-excel-import-content []
  [:div
   (let [{:keys [vendors-not-found errors already-imported imported]}     @(re-frame/subscribe [::result])]
     [:div
      [:h1.title "Import Invoices from Integreat Excel"]
      (when (seq vendors-not-found)
        [create-missing-vendors {:vendors vendors-not-found}]
        )
      [form-builder/builder {:id           ::form
                             :submit-event [::save]}
       [form-builder/raw-field-v2 {:field :excel-rows}
        [:textarea.textarea {:rows         "20"
                             :type         "text"}]]
       [form-builder/error-notification]
       [form-builder/submit-button "Import"]]
      [:div.is-clearfix]
      [:div.is-clearfix
       [:p
        (when imported
          (str imported " rows imported."))]
       [:p
        (when already-imported
          (str already-imported " rows already imported."))]]
      (when errors
        [:div
         [:h3 (str "Import errors (" (min 100 (count errors)) " / " (count errors) " )")]
         [:table.table.is-fullwidth
          [:thead
           [:td "Date"]
           [:td "Invoice #"]
           [:td "Client"]
           [:td "Vendor"]
           [:td "Amount"]
           [:td "Errors"]]

          [:tbody 
           (for [{:keys [raw-date invoice-number client vendor-name amount] row-errors :errors} (take 100 errors)]
             ^{:key (str raw-date invoice-number client vendor-name amount)}
             [:tr
              [:td raw-date]
              [:td invoice-number]
              [:td client]
              [:td vendor-name]
              [:td amount]
              [:td (map (fn [{:keys [info]}] ^{:key info} [:p info]) row-errors)]])]]])])])


(defn admin-excel-import-page-internal []
  [side-bar-layout {:side-bar [admin-side-bar {}]
                    :main [admin-excel-import-content]}])

(re-frame/reg-event-fx
  ::mounted
  (fn [_ _]
    {:dispatch [::forms/start-form ::form]}))

(re-frame/reg-event-fx
  ::unmounted
  (fn [{:keys [db]} _]
    {:dispatch-n [[::forms/form-closing ::form]
                  [::forms/form-closing ::create-vendors]]
     :db (dissoc db ::results)}))

(defn admin-excel-import-page []
  (r/create-class
    {:display-name           "excel-import-page"
     :component-will-unmount #(re-frame/dispatch-sync [::unmounted])
     :component-did-mount    #(re-frame/dispatch [::mounted])
     :reagent-render         admin-excel-import-page-internal}))
