(ns auto-ap.ssr.admin.import-batch
  (:require
   [auto-ap.client-routes :as client-routes]
   [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.routes.admin.import-batch :as route]
   [auto-ap.routes.utils
    :refer [wrap-admin wrap-client-redirect-unauthenticated]]
   [auto-ap.ssr-routes :as ssr-routes]
   [auto-ap.ssr.components :as com]
   [auto-ap.ssr.components.date-range :refer [date-range-field]]
   [auto-ap.ssr.grid-page-helper :as helper :refer [wrap-apply-sort]]
   [auto-ap.ssr.svg :as svg]
   [auto-ap.ssr.utils
    :refer [apply-middleware-to-all-handlers clj-date-schema
            default-grid-fields-schema ref->select-options 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]
   [hiccup.util :as hu]
   [malli.core :as mc]))

(def query-schema (mc/schema
                   [:maybe
                    (into [:map {:date-range [:date-range :start-date :end-date]}
                           [: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
                                  ::route/table)
          "hx-target"          "#entity-table"
          "hx-indicator"       "#entity-table"}

   [:fieldset.space-y-6 
    (date-range-field {:value {:start (:start-date (:query-params request))
                               :end (:end-date (:query-params request))}
                       :id "date-range"})
    (com/field {:label "Source"}
               (com/select {:name        "source"
                            :class       "hot-filter w-full"
                            :value       (:source (:query-params request))
                            :placeholder ""
                            :options (ref->select-options "import-source" :allow-nil? true)}))

    #_(com/field {:label "Code"}
               (com/text-input {:name        "code"
                                :id          "code"
                                :class       "hot-filter"
                                :value       (:code (:query-params request))
                                :placeholder "11101"
                                :size        :small}))]])

(def default-read '[:db/id
                    [:import-batch/date :xform clj-time.coerce/from-date]
                    :import-batch/suppressed
                    :import-batch/extant
                    :import-batch/user-name
                    :import-batch/imported
                    {[:import-batch/source :xform iol-ion.query/ident] [:db/ident]
                     [:import-batch/status :xform iol-ion.query/ident] [:db/ident]}])

(defn fetch-ids [db request]
  (let [query-params (:query-params request)
        query (cond-> {:query {:find  []
                               :in    '[$ ]
                               :where '[]}
                       :args  [db ]}
                (:sort query-params) (add-sorter-fields {"source" ['[?e :import-batch/source ?s]
                                                                   '[?s :db/ident ?s2]
                                                                   '[(name ?s2) ?sort-source]]
                                                         "status" ['[?e :import-batch/status ?st]
                                                                   '[?st :db/ident ?st2]
                                                                   '[(name ?st2) ?sort-status]]
                                                         "user" ['[?e :import-batch/user-name ?sort-user]]
                                                         "date"   ['[?e :import-batch/date ?sort-date]]
                                                         "type"   ['[?e :account/type ?t]
                                                                 '[?t :db/ident ?ti]
                                                                 '[(name ?ti) ?sort-type]]}
                                                        query-params)

                (or (:start-date query-params)
                    (:end-date query-params))
                (merge-query {:query '{:where [[?e :import-batch/date ?d]]}})

                (:start-date query-params)
                (merge-query {:query '{:in    [?start-date]
                                       :where [[(>= ?d ?start-date)]]}
                              :args  [(->  query-params :start-date c/to-date)]})
                
                (:end-date query-params)
                (merge-query {:query '{:in    [?end-date]
                                       :where [[(< ?d ?end-date)]]}
                              :args  [(->  query-params :end-date c/to-date)]})

                (not-empty (:source query-params))
                (merge-query {:query '{:in    [?source]
                                       :where [[?e :import-batch/source ?source]]}
                              :args  [(keyword "import-source" (:source query-params))]})
                true
                (merge-query {:query {:find  ['?sort-default '?e]
                                      :where ['[?e :import-batch/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                 "entity-table"
                 :id-fn :db/id
                 :nav                com/admin-aside-nav
                 :fetch-page         fetch-page
                 :page-specific-nav  filters
                 :row-buttons (fn [_ entity]
                                [(com/a-icon-button {:href     (hu/url (bidi/path-for client-routes/routes :transactions)
                                                                       {:import-batch-id (:db/id entity)})
                                                     :hx-boost true}
                                                    svg/external-link)])
                 :oob-render
                 (fn [request]
                   [(assoc-in (date-range-field {:value {:start (:start-date (:query-params request))
                                                         :end   (:end-date (:query-params request))}
                                                 :id "date-range"}) [1 :hx-swap-oob] true)])
                 :breadcrumbs        [[:a {:href (bidi/path-for ssr-routes/only-routes
                                                                :admin)}
                                       "Admin"]

                                      [:a {:href (bidi/path-for ssr-routes/only-routes
                                                                ::route/page)}
                                       "Import Batches"]]
                 :title       "Import Batches"
                 :entity-name "Batch"
                 :query-schema query-schema
                 :route       ::route/table
                 :headers     [{:key      "date"
                                :name     "Date"
                                :sort-key "date"
                                :render   #(some-> % :import-batch/date (atime/unparse-local atime/standard-time))}
                               {:key      "source"
                                :name     "Source"
                                :sort-key "source"
                                :render   :import-batch/source}
                               {:key      "status"
                                :name     "Status"
                                :sort-key "status"
                                :render   #(some-> % :import-batch/status name)}
                               {:key      "user"
                                :name     "User"
                                :sort-key "user"
                                :render   :import-batch/user-name}
                               {:key    "imported"
                                :name   "imported"
                                :render :import-batch/imported}
                               {:key    "extant"
                                :name   "Pre-existing"
                                :render :import-batch/extant}
                               {:key    "suppresed"
                                :name   "Suppressed"
                                :render :import-batch/suppressed}]}))

(def row* (partial helper/row* grid-page))
(def table* (partial helper/table* grid-page))
(def key->handler
  (apply-middleware-to-all-handlers 
    (->> 
      {::route/page             (helper/page-route grid-page)
       ::route/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)
          (wrap-admin)
          (wrap-client-redirect-unauthenticated)))))
