(ns auto-ap.ssr.company.reports
  (:require
   [amazonica.aws.s3 :as s3]
   [auto-ap.datomic
    :refer [add-sorter-fields apply-pagination apply-sort-3 conn merge-query
            pull-many query2]]
   [auto-ap.graphql.utils :refer [assert-can-see-client is-admin?]]
   [auto-ap.query-params :refer [wrap-copy-qp-pqp]]
   [auto-ap.routes.utils :refer [wrap-client-redirect-unauthenticated
                                 wrap-secure]]
   [auto-ap.ssr-routes :as ssr-routes]
   [auto-ap.ssr.company.reports.expense :as company-expense-report]
   [auto-ap.ssr.company.reports.reconciliation :as company-reconciliation-report]
   [auto-ap.ssr.components :as com]
   [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 html-response
                              wrap-merge-prior-hx wrap-schema-enforce]]
   [auto-ap.time :as atime]
   [bidi.bidi :as bidi]
   [clojure.set :as set]
   [config.core :refer [env]]
   [datomic.api :as dc]
   [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)]))
(def default-read '[:db/id :report/client [:report/created :xform clj-time.coerce/from-date] :report/url :report/name :report/creator])

(defn fetch-ids [db request]

  (let [query-params (:query-params request)
        query (cond-> {:query {:find []
                               :in '[$ [?c ...]]
                               :where '[[?e :report/client ?c]]}
                       :args [db (:trimmed-clients request)]} 

                
                (:sort query-params) (add-sorter-fields {"client" ['[?e :report/client ?c]
                                                           '[?c :client/name ?sort-client]]
                                                 "created" ['[?e :report/created ?sort-created]]
                                                 "creator" ['[?e :report/creator ?sort-creator]]
                                                 "name" ['[?e :report/name ?sort-name]
                                                           ]}
                                                query-params)

                true
                (merge-query {:query {:find ['?sort-default '?e] :where ['[?e :report/created ?sort-default]]}}))]
    (->> (query2 query)
      (apply-sort-3 (update query-params :sort conj {:sort-key "default-2" :asc true}))
      (apply-pagination query-params))))

(defn hydrate-results [ids db request]
  (let [results (->> (pull-many db default-read ids)
                     (group-by :db/id))
        valid-clients (:trimmed-clients request)]
    (->> ids
         (map results)
         (filter identity)
         
         (map first)
         (filter (fn [r]
                   (let [used-clients (set (map :db/id (:report/client r)))]
                     (= used-clients
                        (set/intersection valid-clients
                                          used-clients))))))))

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

(def grid-page
  (helper/build {:id          "report-table"
                 :nav         com/company-aside-nav
                 :fetch-page  fetch-page
                 :breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
                                                         :company)}
                                "My Company"]

                               [:a {:href (bidi/path-for ssr-routes/only-routes
                                                         :company-reports)}
                                "Reports"]]
                 :title          "Reports"
                 :entity-name    "Reports"
                 :query-schema query-schema
                 :route          :company-reports-table
                 :row-buttons    (fn [request e]
                                   [(com/a-icon-button {:href (:report/url e)}
                                                       svg/download)
                                    (when (is-admin? (:identity request))
                                      (com/icon-button {:hx-delete (str (bidi/path-for ssr-routes/only-routes
                                                                                       :company-reports-delete
                                                                                       :request-method :delete))
                                                        :hx-target "closest tr"}
                                                       svg/trash))])
                 :headers        [{:key      "name"
                                   :name     "Name"
                                   :sort-key "name"
                                   :render   :report/name}
                                  {:key      "created-by"
                                   :name     "Created by"
                                   :sort-key "creator"
                                   :render   (fn [report]
                                               (when (:report/creator report)
                                                 (com/pill {:color :primary }
                                                           (:report/creator report))))}
                                  {:key      "created"
                                   :name     "Created"
                                   :sort-key "created"
                                   :render   #(atime/unparse-local (:report/created %)
                                                                   atime/normal-date)}]}))

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

(defn delete-report [{:keys [form-params identity]}]
  
  (let [[id-to-delete key] (first (dc/q '[:find ?i ?k
                                          :in $ ?i
                                          :where [?i :report/key ?k]]
                                        (dc/db conn)
                                        (some-> (get form-params "id") not-empty Long/parseLong)))
        report             (dc/pull (dc/db conn) default-read id-to-delete)]
    (assert-can-see-client identity (:report/client report))
    (when id-to-delete 
      (s3/delete-object :bucket-name (:data-bucket env)
                        :key key)
      @(dc/transact conn [[:db/retractEntity id-to-delete]]))
    (html-response 
      (row* identity
            report
            {:flash?               true
             :delete-after-settle? true}))))


(def key->handler
  (apply-middleware-to-all-handlers
   (->>
     (into 
      {:company-reports        page
       :company-reports-table  table
       :company-reports-delete delete-report}
      company-expense-report/key->handler)
    (into company-reconciliation-report/key->handler))
   (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-secure)
         (wrap-client-redirect-unauthenticated)))))
