(ns auto-ap.ssr.pos.refunds
  (:require
   [auto-ap.datomic
    :refer [add-sorter-fields apply-pagination apply-sort-3 conn merge-query
            pull-many query2]]
   [auto-ap.query-params :refer [wrap-copy-qp-pqp]]
   [auto-ap.ssr-routes :as ssr-routes]
   [auto-ap.ssr.components :as com]
   [auto-ap.ssr.grid-page-helper :as helper :refer [wrap-apply-sort]]
   [auto-ap.ssr.pos.common :refer [date-range-field* total-field*]]
   [auto-ap.ssr.utils :refer [apply-middleware-to-all-handlers clj-date-schema
                              default-grid-fields-schema wrap-merge-prior-hx
                              wrap-schema-enforce]]
   [auto-ap.time :as atime]
   [bidi.bidi :as bidi]
   [clj-time.coerce :as c]
   [datomic.api :as dc]
   [malli.core :as mc]))

(def query-schema (mc/schema
                   [:maybe
                    (into [:map {:date-range [:date-range :start-date :end-date]}
                           [:total-gte {:optional true} [:maybe :double]]
                           [:total-lte {:optional true} [:maybe :double]]
                           [:start-date {:optional true}
                            [:maybe clj-date-schema]]
                           [:end-date {:optional true}
                            [:maybe clj-date-schema]]
                           [:client {:optional true :default nil} [:maybe  [:entity-map {:pull [:db/id :client/name]}]]]]
                          default-grid-fields-schema)]))
(defn filters [request]
  [:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
          "hx-get" (bidi/path-for ssr-routes/only-routes
                                  :pos-refund-table)
          "hx-target" "#refund-table"
          "hx-indicator" "#refund-table"
          #_#_:hx-disabled-elt "find fieldset"}

   [:fieldset.space-y-6 
    (date-range-field* request)
    (total-field* request)]])

(def default-read '[:db/id
                    :sales-refund/total
                    :sales-refund/fee
                    :sales-refund/type
                    [:sales-refund/date :xform clj-time.coerce/from-date]
                    {:sales-refund/client [:client/name :db/id :client/code]}])

(defn fetch-ids [db request]
  (let [query-params (:query-params request)
        query (cond-> {:query {:find  []
                               :in    ['$ '[?clients ?start-date ?end-date]]
                               :where '[[(iol-ion.query/scan-sales-refunds $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]]}
                       :args  [db [(:trimmed-clients request)
                                   (some->  query-params :start-date c/to-date)
                                   (some-> query-params :end-date c/to-date )]]}
                (:sort query-params) (add-sorter-fields {"client" ['[?e :sales-refund/client ?c]
                                                                   '[?c :client/name ?sort-client]]
                                                         "date" ['[?e :sales-refund/date ?sort-date]]
                                                         "total" ['[?e :sales-refund/total ?sort-total]]
                                                         "fee" ['[?e :sales-refund/fee ?sort-tip]]
                                                         "type" ['[?e :sales-refund/type ?sort-type]]}
                                                        query-params)

                (:exact-match-id query-params)
                (merge-query {:query {:in ['?e]
                                      :where []}
                              :args [(:exact-match-id query-params)]})

                (:total-gte query-params) 
                (merge-query {:query {:in ['?total-gte]
                                      :where ['[?e :sales-refund/total ?a]
                                              '[(>= ?a ?total-gte)]]}
                              :args [(:total-gte query-params)]})

                (:total-lte query-params) 
                (merge-query {:query {:in ['?total-lte]
                                      :where ['[?e :sales-refund/total ?a]
                                              '[(<= ?a ?total-lte)]]}
                              :args [(:total-lte query-params)]})

                true
                (merge-query {:query {:find ['?sort-default '?e]
                                      :where ['[?e :sales-refund/date ?sort-default]]}}))]
    
    (cond->> (query2 query)
      true (apply-sort-3 query-params)
      true (apply-pagination query-params))))

(defn hydrate-results [ids db _]
  (let [results (->> (pull-many db default-read ids)
                     (group-by :db/id))
        refunds (->> ids
                     (map results)
                     (map first))]
    refunds))

(defn fetch-page [request]
  (let [db                                           (dc/db conn)
        {ids-to-retrieve :ids matching-count :count} (fetch-ids db request)]

    [(->> (hydrate-results ids-to-retrieve db request))
     matching-count]))

(def grid-page
  (helper/build {:id                 "refund-table"
                 :nav                com/main-aside-nav
                 :page-specific-nav  filters
                 :fetch-page         fetch-page
                 :oob-render
                 (fn [request]
                   [(assoc-in (date-range-field* request) [1 :hx-swap-oob] true)])
                 :breadcrumbs        [[:a {:href (bidi/path-for ssr-routes/only-routes
                                                                :company)}
                                       "POS"]

                                      [:a {:href (bidi/path-for ssr-routes/only-routes
                                                                :pos-refunds)}
                                       "Refunds"]]
                 :title          "Refunds"
                 :entity-name    "Refund"
                 :query-schema query-schema
                 :route          :pos-refund-table
                 :headers        [{:key      "client"
                                   :name     "Client"
                                   :sort-key "client"
                                   :hide?    (fn [args]
                                               (= (count (:clients args)) 1))
                                   :render   #(-> % :sales-refund/client :client/code)}
                                  {:key      "date"
                                   :name     "Date"
                                   :sort-key "date"
                                   :render   #(atime/unparse-local (:sales-refund/date %) atime/standard-time)}
                                  {:key      "total"
                                   :name     "Total"
                                   :sort-key "total"
                                   :render   #(some->> % :sales-refund/total (format "$%.2f"))}
                                  {:key      "type"
                                   :name     "Type"
                                   :sort-key "type"
                                   :render   :sales-refund/type}
                                  {:key      "fee"
                                   :name     "Fee"
                                   :sort-key "fee"
                                   :render   #(some->> % :sales-refund/fee (format "$%.2f"))}]}))

(def row* (partial helper/row* grid-page))
(def table* (partial helper/table* grid-page))

(def key->handler
  (apply-middleware-to-all-handlers 
   {:pos-refunds       (helper/page-route grid-page)
    :pos-refund-table (helper/table-route grid-page)}
   (fn [h]
      (-> h
          (wrap-copy-qp-pqp)
          (wrap-apply-sort grid-page)
          (wrap-merge-prior-hx)
          (wrap-schema-enforce :query-schema query-schema)
          (wrap-schema-enforce :hx-schema query-schema)))))
