(ns auto-ap.views.pages.invoices.advanced-print-checks
  (: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.components.money-field :refer [money-field]]
   [auto-ap.views.pages.invoices.common
    :refer [does-amount-exceed-outstanding? invoice-read]]
   [auto-ap.views.utils :refer [coerce-float dispatch-event with-user]]
   [malli.core :as m]
   [re-frame.core :as re-frame]))

(def advanced-print-schema (m/schema
                             [:and
                              [:map
                               [:bank-account-id schema/not-empty-string]
                               [:invoice-amounts [:map-of
                                                  :string
                                                  [:map
                                                   [:amount schema/money]]]]]
                              [:fn (fn [{:keys [invoices invoice-amounts]}]
                                     (if (seq (filter
                                                  (fn [{:keys [id outstanding-balance]}]
                                                    (does-amount-exceed-outstanding? (get-in invoice-amounts [id :amount]) outstanding-balance ))
                                                  invoices))
                                       (throw (ex-info "Invalid" {:type ::too-much-invoice}))
                                       true))]]))

(defn form []
  (let [real-bank-accounts @(re-frame/subscribe [::subs/real-bank-accounts])
        {:keys [data]}     @(re-frame/subscribe [::forms/form ::form])]

    [form-builder/builder {:submit-event [::try-save]
                           :id           ::form
                           :schema advanced-print-schema}
     [form-builder/field-v2 {:field :bank-account-id}
      "Pay using"
      [com/select-field {:options    (for [{:keys [id name]} real-bank-accounts]
                                       [id name])
                         :allow-nil? true}]]

     [:table.table.is-fullwidth
      [:thead
       [:tr
        [:th "Vendor"]
        [:th "Invoice ID"]
        [:th {:style {"width" "10em"}} "Payment"]]]
      [:tbody
       (doall
         (for [{:keys [vendor invoice-number id]} (:invoices data)]
           ^{:key id}
           [:tr
            [:td (:name vendor)]
            [:td invoice-number]
            
            [:td
             [form-builder/raw-field-v2 {:field [:invoice-amounts id :amount]}
              [money-field]]]]))]]]))

(re-frame/reg-event-fx
 ::show
 (fn [{:keys [db]} [_ invoices]]
   {:dispatch [::modal/modal-requested {:title   "Print Checks"
                                        :body    [form]
                                        :confirm {:value       "Print checks"
                                                  :status-from [::status/single ::form]
                                                  :class       "is-primary"
                                                  :on-click    (dispatch-event [::try-save])
                                                  :close-event [::status/completed ::form]}}]
    :db       (-> db
            (forms/start-form ::form
                              {:invoices invoices
                               :invoice-amounts (into {}
                                                      (map (fn [i] [(:id i)
                                                                    {:amount (coerce-float (:outstanding-balance i))}])
                                                           invoices))}))}))



(re-frame/reg-event-fx
  ::try-save
  [(forms/in-form ::form)]
  (fn [{:keys [db]}]
    #_(println (m/explain advanced-print-schema (:data db)))
    (if (not (m/validate advanced-print-schema (:data db)))
      {:dispatch-n [[::status/error ::form [{:message "Please correct any errors and try again"}]]
                    [::forms/attempted-submit ::form]]}
      {:dispatch [::save]})))

(re-frame/reg-event-fx
 ::save
 [with-user (forms/in-form ::form) ]
 (fn [{:keys [db user]} _]

   (let [type (or (->> @(re-frame/subscribe [::subs/client])
                       :bank-accounts
                       (filter #(= (:bank-account-id (:data db)) (:id %)))
                       first
                       :type)
                  :check)
         {:keys [invoices invoice-amounts bank-account-id]} (:data db)]
     {:graphql
      {:token user
       :owns-state {:single ::form}
       :query-obj {:venia/operation {:operation/type :mutation
                                     :operation/name "PrintChecks"}
                   
                   :venia/queries [[:print-checks
                                    {:invoice_payments (map (fn [x]
                                                              {:invoice-id (:id x)
                                                               :amount (get-in invoice-amounts [(:id x) :amount])})
                                                            invoices)
                                     :type type
                                     :bank_account_id bank-account-id
                                     :client_id (->> invoices first :client :id)}
                                    [[:invoices invoice-read]
                                     :pdf_url]]]}
       :on-success (fn [result]
                     [::checks-printed
                      (:invoices (:print-checks result))
                      (:pdf-url (:print-checks result))])}})))

(re-frame/reg-event-fx
 ::checks-printed
 (fn [{:keys [_]} [_ _]]
   {:dispatch [::modal/modal-closed]}))

