(ns auto-ap.views.pages.admin.excel-import
  (:require [auto-ap.events :as all-events]
            [auto-ap.forms :as forms]
            [auto-ap.subs :as subs]
            [auto-ap.views.components.admin.side-bar :refer [admin-side-bar]]
            [auto-ap.views.components.layouts :refer [side-bar-layout]]
            [auto-ap.views.components.typeahead :refer [typeahead-v3]]
            [auto-ap.views.utils :refer [bind-field dispatch-event]]
            [re-frame.core :as re-frame]))

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

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

(re-frame/reg-event-db
 ::change
 (fn  [db [_ field v]]
   (assoc-in db (into [::excel-import]  field) v)))



(re-frame/reg-event-fx
 ::save
 [(forms/in-form ::excel-import)]
 (fn [{{excel-import-data :data :as excel-import-form} :db}]
   (let [user @(re-frame/subscribe [::subs/token])]
     {:db (-> excel-import-form
              (assoc :status :loading)
              (assoc :error nil))
      :http {:token user
             :method :post 
             :body (pr-str excel-import-data)
             :headers {"Content-Type" "application/edn"}
             :uri (str "/api/invoices/upload-integreat")
             :on-success [::save-complete]
             :on-error [::forms/save-error ::excel-import]}})))

(re-frame/reg-event-fx
 ::save-complete
 (fn [{:keys [db]} [_ rows]]
   {:db
    (-> db
        (forms/save-succeeded ::excel-import)
        (assoc-in [::excel-import :rows] rows))}))

(re-frame/reg-event-fx
 ::save-error
 (fn [{:keys [db]}]
   (println "ERROR")
   {:dispatch [::change [:error] true]
    :db (-> db
            (assoc-in [::excel-import :rows] nil)
            (assoc-in [::excel-import :saving?] false))}))

(re-frame/reg-event-db
 ::toggle-vendor
 (fn [db [_ data]]
   (update-in db [::excel-import :create-vendors] (fn [x]
                                            (let [x (or x #{})]
                                              (if (x data)
                                                (disj x data)
                                                (conj x data)))))))
(re-frame/reg-event-fx
 ::create-vendors
 (fn [{:keys [db]}]
   (let [excel-import (::excel-import db)]
     (println (::expense-accounts db))
     {:graphql {:token (:user db)
                :query-obj {:venia/operation {:operation/type :mutation
                                              :operation/name "UpsertVendor"}
                            
                            :venia/queries (map (fn [v ]
                                                  {:query/data [:upsert-vendor
                                                                {:vendor {:name v :default-account-id (-> db ::expense-accounts (get v) :default-account-id :id)}}
                                                                [:id :name]]})

                                                (get-in db [::excel-import :create-vendors]))}
              :on-success [::create-vendor-complete]
              :on-error [::create-vendor-error]}
      :db (-> db 
              (assoc-in [::excel-import :saving-vendors?] true))})))


(re-frame/reg-event-db
 ::create-vendor-complete
 (fn [db [_ data]]
   (-> db
       (update-in [::excel-import :rows :vendors-not-found]
                  (fn [v]
                    (reduce disj v (get-in db [::excel-import :create-vendors]))))
       (update-in [::excel-import] dissoc :create-vendors))))

(defn admin-excel-import-content []
  [:div
   (let [{{:keys [vendors-not-found already-imported imported]} :rows
          :keys [create-vendors]
          :or {create-vendors #{}}
          :as excel-import-data} @(re-frame/subscribe [::excel-import])
         data @(re-frame/subscribe [::expense-accounts])
         form @(re-frame/subscribe [::forms/form ::excel-import])
         

         chooseable-expense-accounts @(re-frame/subscribe [::subs/all-accounts])
         change-event [::all-events/change-form [::expense-accounts]]]
     (println form)
     [:div
      [:h1.title "Import Invoices from Integreat Excel"]
      (when (seq vendors-not-found)
        [: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"]
          [:div.columns
           (for [[i vendor-group] (map vector (range) (partition-all (max 1 (/ (count vendors-not-found) 3)) vendors-not-found))]
             ^{:key i}
             [:div.column
              (for [v vendor-group]
                ^{:key v} [:div.field.is-grouped
                           [:p.control
                            [:label.checkbox
                             [:input {:value v
                                      :checked (if (create-vendors v)
                                                 "checked"
                                                 "")

                                      :type "checkbox"
                                      :on-change (fn []
                                                   (re-frame/dispatch [::toggle-vendor v]))}]
                             (str " " v)]]

                           [:p.control
                            [bind-field
                             [typeahead-v3 {:entities chooseable-expense-accounts
                                            :entity->text (fn [x ] (str (:numeric-code x) " - " (:name x)))
                                            :type "typeahead-v3"
                                            :field [v :default-account-id]
                                            :event change-event
                                            :subscription data}]]]])])]
          [:div
           [:button.button.is-pulled-right
            {:on-click (dispatch-event [::create-vendors])
             :disabled (when-not (seq create-vendors)
                         "disabled")
             }
            (str "Create " (count create-vendors) " vendors")]]
          [:div.is-clearfix]]])
      [bind-field
       [:textarea.textarea {:rows "20"
                            :field :excel-rows
                            :type "text"
                            :event [::forms/change ::excel-import]
                            :subscription (:data form)}]]
      
      [:button.button.is-large.is-pulled-right.is-primary  {:on-click (dispatch-event [::save])
                                                            :class (str @(re-frame/subscribe [::forms/loading-class ::excel-import])
                                                                        (when (:error form) " animated shake"))
                                                            :disabled (when (= :saving (:status form)) "disabled")} "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-let [errors (:errors (:rows excel-import-data))]
        [:div
         [:h3 (str "Import errors (" (min 100 (count errors)) " / " (count errors) " )")]
         [:table.table.is-fullwidth
          [:thead
           [:th "Date"]
           [:th "Invoice #"]
           [:th "Client"]
           [:th "Vendor"]
           [:th "Amount"]
           [:th "Errors"]]

          (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 []
  [side-bar-layout {:side-bar [admin-side-bar {}]
                    :main [admin-excel-import-content]}])
