(ns auto-ap.ssr.company.reports.reconciliation
  (:require [auto-ap.datomic :refer [conn pull-attr]]
            [auto-ap.graphql.utils :refer [extract-client-ids]]
            [auto-ap.import.intuit :refer [get-intuit-bank-accounts
                                           intuits->transactions]]
            [auto-ap.intuit.core :refer [get-transactions]]
            [auto-ap.ssr-routes :as ssr-routes]
            [auto-ap.ssr.components :as com]
            [auto-ap.ssr.form-cursor :as fc]
            [auto-ap.ssr.hx :as hx]
            [auto-ap.ssr.ui :refer [base-page]]
            [auto-ap.ssr.utils :refer [apply-middleware-to-all-handlers
                                       clj-date-schema html-response
                                       wrap-schema-enforce]]
            [auto-ap.time :as atime]
            [bidi.bidi :as bidi]
            [cemerick.url :as url]
            [clj-time.coerce :as coerce]
            [datomic.api :as dc]
            [auto-ap.ssr.svg :as svg]))

(defn report* [{:keys [request report]}]
  [:div #_{:class "overflow-scroll min-w-full max-h-[700px]"}
   (com/data-grid
    {:headers (into
               [(com/data-grid-header {} "Bank Account")
                (com/data-grid-header {} "Source count")
                (com/data-grid-header {} "Synced count")
                (com/data-grid-header {} "Approved transactions")
                (com/data-grid-header {} "Unapproved transactions")
                (com/data-grid-header {} "Requires feedback transactions")
                (com/data-grid-header {} "Missing transactions")])
     #_#_:thead-params {:class "sticky top-0 z-50"}}
    (for [row report]
      (let [matches? (= (:external-transaction-count row)
                        (:integreat-transaction-count row))
            class (if matches? "bg-primary-200 text-primary-900"
                      "bg-red-200 text-red-900")]
        (com/data-grid-row
         {}
         (com/data-grid-cell {:class class}
                             (:bank-account/name row))
         (com/data-grid-cell {:class class}
                             (:external-transaction-count row))
         (com/data-grid-cell {:class class}
                             (:integreat-transaction-count row))
         (com/data-grid-cell {:class class}
                             (:approved-count row))
         (com/data-grid-cell {:class class}
                             (:unapproved-count row))
         (com/data-grid-cell {:class class}
                             (:requires-feedback-count row))
         (com/data-grid-cell {:class class}
                             (when (> (count (:missing-transactions row)) 0)
                               [:div
                                (com/button { :x-tooltip.on.click "{content: ()=>$refs.tooltip.innerHTML, theme: 'light', allowHTML: true}" }
                                            [:div.flex.gap-2.items-center
                                             (count (:missing-transactions row))
                                             [:div.w-4.h-4 svg/question]])
                                [:template {:x-ref "tooltip"}
                                 (com/data-grid {:headers [(com/data-grid-header {} "Date")
                                                           (com/data-grid-header {} "Amount")]}
                                                (for [r (:missing-transactions row)]
                                                  (com/data-grid-row {}
                                                                     (com/data-grid-cell {}
                                                                                         (atime/unparse-local (coerce/to-date-time (:transaction/date r)) atime/normal-date))
                                                                     (com/data-grid-cell {}
                                                                                         (format "$%,.2f" (:transaction/amount r))))))]]))))))])


(defn reconciliation-card* [{:keys [request report]}]
  (com/content-card {:class "w-full" :id "reconciliation-report"}
                    [:div {:class "flex flex-col px-8 py-8 space-y-3"}
                     [:div
                      [:h1.text-2xl.mb-3.font-bold "Bank Reconciliation Report"]
                      
                      [:form {:hx-get (bidi.bidi/path-for ssr-routes/only-routes :company-reconciliation-report-card)
                              :hx-target "#reconciliation-report"
                              :hx-swap "outerHTML"}
                       (fc/start-form
                        (:query-params request)
                        (:form-errors request)
                        [:div.flex.gap-2
                         (fc/with-field :start-date
                           (com/validated-field {:label "Start"
                                                 :errors (fc/field-errors)}
                                                [:div {:class "w-64"}
                                                 (com/date-input {:name        (fc/field-name)
                                                                  :class "w-64"
                                                                  :value       (some-> (fc/field-value)
                                                                                       (atime/unparse-local atime/normal-date)) })]))
                         (fc/with-field :end-date
                           (com/validated-field {:label "End"
                                                 :errors (fc/field-errors)}
                                                [:div {:class "w-64"}
                                                 (com/date-input {:name        (fc/field-name)
                                                                  :class "w-64"
                                                                  :value       (some-> (fc/field-value)
                                                                                       (atime/unparse-local atime/normal-date)) })]))
                         (com/button {:color :primary :class "self-center w-24"} "Run")])]
(if report 
                        (report* {:request request :report report})
                        [:div "Please choose a time range to run the report"])
                      ]]))

(defn page [request]
  (base-page
   request
   (com/page {:nav           com/company-aside-nav
              :client-selection (:client-selection request)
              :client (:client request)
              :clients (:clients request)
              :identity      (:identity request)
              :app-params {:hx-get     (bidi/path-for ssr-routes/only-routes :company-reconciliation-report)
                           :hx-trigger "clientSelected from:body"
                           :hx-select "#app-contents"
                           :hx-swap    "outerHTML swap:300ms"}}
             (com/breadcrumbs {}
                              [:a {:href (bidi/path-for ssr-routes/only-routes :company)}
                               "My Company"]
                              [:a {:href (bidi/path-for ssr-routes/only-routes :company-reconciliation-report)}
                               "Reconciliation Report"])
             (reconciliation-card* {:request request :report nil}))
   "My Company"))

(defn normalize-query-params [request]
  (-> request
      :query-params
      (update :vendor-id :db/id)
      (update :account-id :db/id)
      (update :start-date #(atime/unparse-local % atime/normal-date))
      (update :end-date #(atime/unparse-local % atime/normal-date))

      url/map->query))

(defn get-report-data [start-date end-date client-ids]
  (let [client-codes (map first (dc/q '[:find ?cc :in $ [?c ...] :where [?c :client/code ?cc]] (dc/db conn ) client-ids))]
    (for [[ib ba c] (seq (apply get-intuit-bank-accounts  (dc/db conn) client-codes))
          :let [raw-transactions (get-transactions (atime/unparse-local start-date atime/iso-date)
                                                   (atime/unparse-local end-date atime/iso-date)
                                                   ib)
                ideal-transactions (intuits->transactions raw-transactions ba c)

                found-transactions (when (seq ideal-transactions)
                                     (into {} (dc/q '[:find ?si (count ?t)
                                                      :in $ [?eid ...]
                                                      :where
                                                      [?t :transaction/id ?eid]
                                                      [?t :transaction/approval-status ?s]
                                                      [?s :db/ident ?si]]
                                                    (dc/db conn)
                                                    (map :transaction/id ideal-transactions))))

                missing-transaction-ids (when (seq ideal-transactions)
                                          (->>
                                           (dc/q '[:find ?eid
                                                   :in $ [?eid ...]
                                                   :where (not [_ :transaction/id ?eid])]
                                                 (dc/db conn)
                                                 (map :transaction/id ideal-transactions))
                                           (map first)
                                           (into #{})))
                missing-transactions (filter (comp missing-transaction-ids :transaction/id) ideal-transactions)]]
      {:bank-account/name (pull-attr (dc/db conn) :bank-account/name ba)
       :external-transaction-count (count raw-transactions)
       :integreat-transaction-count (reduce + 0 (vals found-transactions))
       :approved-count (:transaction-approval-status/approved found-transactions 0)
       :unapproved-count (:transaction-approval-status/unapproved found-transactions 0)
       :requires-feedback-count (:transaction-approval-status/requires-feedback found-transactions 0)
       :missing-transactions missing-transactions})))

(defn card [{ {:keys [start-date end-date]} :query-params :as request}]
  (let [client-ids (extract-client-ids (:clients request)
                                          (:client-id request)
                                          (when (:client-code request)
                                            [:client/code (:client-code request)]))
        report (get-report-data start-date end-date client-ids)]
    (html-response
     (reconciliation-card* {:request request
                            :report report})
     :headers {"hx-push-url" (str "?" (normalize-query-params request))})))

(def key->handler
  (apply-middleware-to-all-handlers
   {:company-reconciliation-report page 
    :company-reconciliation-report-card card}
   (fn [h]
     (-> h
         (wrap-schema-enforce :query-schema
                              [:map {:default {}}
                               [:start-date {:optional true}
                                [:maybe clj-date-schema]]
                               [:end-date {:optional true}
                                [:maybe clj-date-schema]] ])))))