(ns auto-ap.views.components.expense-accounts-field
  (:require
   [auto-ap.forms.builder :as form-builder]
   [auto-ap.schema :as schema]
   [auto-ap.utils :refer [dollars-0?]]
   [auto-ap.views.components :as com]
   [auto-ap.views.components.button-radio :as button-radio]
   [auto-ap.views.components.level :refer [left-stack]]
   [auto-ap.views.components.money-field :refer [money-field]]
   [auto-ap.views.components.percentage-field :refer [percentage-field]]
   [auto-ap.views.components.typeahead.vendor
    :refer [search-backed-typeahead]]
   [auto-ap.views.utils :refer [->$ appearing-group]]
   [goog.string :as gstring]
   [malli.core :as m]))

(defn can-replace-with-default? [accounts]
  (and (or (not (seq accounts))
           (<= 1 (count accounts)))
       (not (get-in accounts [0 :account :id]))))

(defn default-account [accounts default-account amount locations]
  [{:id (str "new-" (random-uuid))
    :amount (Math/abs amount)
    :amount-percentage 100
    :amount-mode "%"
    :location (or
               (:location default-account)
               (get-in accounts [0 :account :location])
               (if (= 1 (count locations))
                 (first locations)
                 nil))
    :account default-account}])


(defn from-graphql [accounts total locations]
  (if (seq accounts)
    (vec (map
          (fn [a]
            (-> a 
                (update :amount js/parseFloat)
                (assoc :amount-percentage  (* 100 (/ (js/parseFloat (:amount a))
                                                     (Math/abs total))))
                (assoc :amount-mode "$")))
          accounts))
    [{:id (str "new-" (random-uuid))
      :amount-mode "$"
      :amount (Math/abs total)
      :amount-percentage 100
      :location (if (= 1 (count locations))
                  (first locations)
                  nil)}]))


;; EVENTS

(defn recalculate-amounts [expense-accounts total]
  (mapv
   (fn [ea]
     (assoc ea :amount 
            (js/parseFloat
             (goog.string/format "%.2f"
                                 (* (/ (js/parseFloat (:amount-percentage ea)) 100.0) total)))))
   expense-accounts))

;; VIEWS


(def schema (m/schema [:sequential [:map
                                    [:id :string]
                                    [:account schema/reference]
                                    [:location schema/not-empty-string]
                                    [:amount schema/money]]]))




(defn expense-accounts-field-v2 [{value :value on-change  :on-change allowance :allowance expense-accounts :value client :client max-value :max locations :locations  disabled :disabled percentage-only? :percentage-only? :or {percentage-only? false} vendor-id :vendor-id}]
  [form-builder/virtual-builder {:value     value
                                 :schema schema
                                 :on-change (fn [expense-accounts original-expense-accounts]
                                              (let [updated-expense-accounts 
                                                    (for [[before-account after-account] (map vector (concat  original-expense-accounts
                                                                                                              (repeat nil)) expense-accounts)]
                                                      (cond-> after-account
                                                        (and
                                                         (not (:location (:account after-account)))
                                                         (= 1 (count locations)))
                                                        (assoc :location (first locations))

                                                        (:location (:account before-account))
                                                        (assoc :location nil)

                                                        (not= (:amount-percentage before-account)
                                                              (:amount-percentage after-account))
                                                        (assoc :amount (* (/ (:amount-percentage after-account) 100.0)
                                                                          max-value))

                                                        (:location (:account after-account))
                                                        (assoc :location (:location (:account after-account)))))]
                                                (on-change (into [] updated-expense-accounts))))}
   [:div
    [:div.tags
     (when (and max-value (not percentage-only?))
       [:div.tag "To Allocate: " (->$ max-value)])

     (when-not percentage-only?
       (let [total (reduce + 0 (map (or :amount 0.0) expense-accounts))]
         [:<> 
          [:div.tag "Total: " (->$ total) ]
          [:div.tag {:class (if (dollars-0? (- max-value total))
                              ["is-primary" "is-light"]
                              ["is-danger" "is-light"])}
           "Remaining: " (->$ (- max-value total))]]))]

    (into [appearing-group]
          (for [[index {:keys [account id amount amount-mode]}] (map vector (range) expense-accounts)]
             ^{:key id}
             [:div.card {:style {:margin-bottom "2em"}}
              [:div.card-header 
               [:p.card-header-title "Expense Account"]
               (when-not disabled
                 [:div.card-header-icon  {:on-click (fn []
                                                      (on-change (into [] (filter #(not= id (:id %)) expense-accounts))))}
                  [:a.delete ]])]
              [:div.card-content
               [:div.field
                [:div.columns
                 [:div.column
                  [:div.control.is-fullwidth
                   [form-builder/field-v2 {:required? true
                                           :field     [index :account]} 
                    "Account"
                    [search-backed-typeahead {:search-query (fn [i]
                                                              [:search_account
                                                               {:query     i
                                                                :allowance allowance
                                                                :client-id (:id client)
                                                                :vendor-id vendor-id}
                                                               [:name :id :location :warning]])
                                              :disabled     disabled}]]]]
                 [:div.column.is-narrow
                  [form-builder/field-v2 {:required? true
                                          :field     [index :location]}
                   "Location"
                   [com/select-field {:options    (if (:location account)
                                                [[(:location account) (:location account)]]
                                                (map (fn [l] [l l])
                                                     locations))
                                  :disabled   (boolean (:location account))
                                  :allow-nil? true}]]]]]
               (when-let [warning (:warning account)]
                 [:div.notification.is-warning.is-small.is-light {:style {:padding "0.5rem 1.25rem"}}
                  warning])
               (if percentage-only?
                 [form-builder/raw-field-v2 {:field [index :amount-percentage]}
                  [percentage-field {}]]
                 [left-stack 
                  [:div.field.has-addons 
                   [form-builder/raw-field-v2 {:field [index :amount-mode]}
                    [button-radio/button-radio {:options [["$" "Amount"]
                                                          ["%" "Percent"]]}]]
                   (if (= "$" amount-mode)
                     [form-builder/raw-field-v2 {:field [index :amount]}
                      [money-field {}]
                      ]
                     [form-builder/raw-field-v2 {:field [index :amount-percentage]}
                      [percentage-field {}]])]
                  (when (= "%" amount-mode)
                    [:div.tag.is-primary.is-light (gstring/format "$%.2f" (or amount 0) )])])]]))
    (when-not disabled 
      [:p.buttons
       [:a.button {:on-click (fn []
                               (on-change
                                 (recalculate-amounts (mapv
                                                        (fn [ea]
                                                          (assoc ea :amount-percentage (* 100.0 (/ 1 (count expense-accounts)))))
                                                        expense-accounts)
                                                      max-value))
                               )} "Spread evenly"]
       [:a.button {:on-click
                   (fn []
                     (on-change (conj value {:id          (str "new-" (random-uuid))
                                             :amount-mode "%"
                                             :location    (if (= 1 (count locations))
                                                            (first locations)
                                                            nil)})))}
        "Add"]])]])
