(ns auto-ap.ssr.company.company-1099
  (:require
   [auto-ap.datomic :refer [apply-pagination-raw conn]]
   [auto-ap.graphql.utils :refer [assert-can-see-client]]
   [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.components :as com]
   [auto-ap.ssr.form-cursor :as fc]
   [auto-ap.ssr.grid-page-helper :as helper :refer [wrap-apply-sort]]
   [auto-ap.ssr.nested-form-params :refer [wrap-nested-form-params]]
   [auto-ap.ssr.svg :as svg]
   [auto-ap.ssr.utils
    :refer [apply-middleware-to-all-handlers default-grid-fields-schema
            entity-id html-response main-transformer modal-response
            ref->enum-schema ref->select-options strip wrap-entity
            wrap-form-4xx-2 wrap-merge-prior-hx wrap-schema-enforce]]
   [bidi.bidi :as bidi]
   [clojure.string :as str]
   [datomic.api :as dc]
   [hiccup.util :refer [url]]
   [malli.core :as mc]))

(def query-schema (mc/schema
                   [:maybe
                    (into [:map  {} ]
                          default-grid-fields-schema)]))

(def vendor-read '[:db/id
                  :vendor/name
                  {:vendor/legal-entity-1099-type [:db/ident]}
                  {:vendor/legal-entity-tin-type [:db/ident]}
                  {:vendor/address [:address/street1
                                    :address/city
                                    :address/state
                                    :address/zip]}
                   {:vendor/default-account [:account/name]}
                  :vendor/legal-entity-tin
                  :vendor/legal-entity-name
                  :vendor/legal-entity-first-name
                  :vendor/legal-entity-middle-name
                  :vendor/legal-entity-last-name])

(defn sum-for-client-vendor [client-id vendor-id]
  (ffirst (dc/q '[:find
                  (sum ?a)
                  :with ?d 
                  :in $ ?c ?v
                  :where
                  [?p :payment/client ?c]
                  [?p :payment/date ?d ]
                  [(>= ?d #inst "2025-01-01T08:00")]
                  [(< ?d #inst "2026-01-01T08:00")]
                  [?p :payment/type :payment-type/check]
                  [?p :payment/amount ?a]
                  [?p :payment/vendor ?v]]
                (dc/db conn)
                client-id
                vendor-id)))

(defn fetch-page [{:keys [trimmed-clients query-params] :as request user :identity}]
  (let [results (dc/q '[:find
                        (pull ?c [:client/code :db/id])
                        (pull ?v vendor-read)
                        (sum ?a)
                        :with ?d 
                        :in $ [?c ...] vendor-read
                        :where
                        [?p :payment/client ?c]
                        [?p :payment/date ?d ]
                        [(>= ?d #inst "2025-01-01T08:00")]
                        [(< ?d #inst "2026-01-01T08:00")]
                        [?p :payment/type :payment-type/check]
                        [?p :payment/amount ?a]
                        [?p :payment/vendor ?v]]
                      (dc/db conn)
                      trimmed-clients
                      vendor-read)
        all (->> results
                   (filter (fn [[_ _ a]]
                             (>= (or a 0.0) 600.0)))
                   (sort-by (fn [[client _ amount]]
                              [(:client/code client ) amount]))
                   (into []))
        paginated (apply-pagination-raw {:start (:start query-params)
                                         :per-page (:per-page query-params)} all)]
    [(:entries paginated) (:count paginated)]))

(def grid-page
  (helper/build 
    {:id          "entity-table"
     :nav         com/company-aside-nav
     :id-fn       (comp :db/id second)
     :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-1099)}
                    "1099 Vendor Info"]]
     :title          "1099 Vendors"
     :entity-name    "Vendors"
                 :query-schema query-schema
     :route          :company-1099-vendor-table
     :row-buttons    (fn [request e]
                       [(com/icon-button {:hx-get    (url (bidi/path-for ssr-routes/only-routes
                                                                         :company-1099-vendor-dialog
                                                                         :vendor-id (:db/id (second e)))
                                                          {:client-id (:db/id (first e))})}
                                         svg/pencil)])
     :headers        [{:key      "Client"
                       :name     "Client"
                       :sort-key "client"
                       :render   (comp :client/code first)}
                      {:key      "vendor-name"
                       :name     "Vendor Name"
                       :sort-key "vendor"
                       :render   (fn [[_ vendor]]
                                   [:div.flex.whitespace-nowrap.items-center.gap-4
                                    [:div [:div (:vendor/name vendor)]
                                     [:div.text-sm.text-gray-400
                                      (or (-> vendor :vendor/legal-entity-name not-empty)
                                          (str (-> vendor :vendor/legal-entity-first-name) " "
                                               (-> vendor :vendor/legal-entity-middle-name) " "
                                               (-> vendor :vendor/legal-entity-last-name)))]]
                                    (when-let [t99-type (some-> vendor :vendor/legal-entity-1099-type :db/ident name)]
                                      (com/pill
                                       {:class "text-xs font-medium"
                                        :color :primary}
                                       (str/capitalize t99-type))
                                      )])}
                      {:key           "tin"
                       :name          "TIN"
                       :sort-key      "tin"
                       :show-starting "md"
                       :render        (fn [[_ vendor]]
                                        [:div.flex.gap-4
                                         (when-let [tin (-> vendor :vendor/legal-entity-tin)]
                                           [:span {:class "text-xs font-medium py-0.5 "} 
                                            tin])
                                         (when-let [tin-type (some-> vendor :vendor/legal-entity-tin-type :db/ident name)]
                                           (com/pill {:class "text-xs font-medium"
                                                      :color :yellow}
                                                     (name tin-type)))]
                                        )}
                      {:key           "expense-account"
                       :name          "Expense Account"
                       :show-starting "md"
                       :render        (fn [[_ vendor]]
                                        [:div.flex.gap-4
                                         (when-let [tin (-> vendor :vendor/default-account :account/name)]
                                           [:span {:class "text-xs font-medium py-0.5 "} 
                                            tin]) ])}
                      {:key           "address"
                       :name          "Address"
                       :sort-key      "address"
                       :show-starting "lg" 
                       :render        (fn [[_ vendor]]
                                        (if (-> vendor :vendor/address :address/street1)
                                          [:div
                                           [:div (-> vendor :vendor/address :address/street1)] " "
                                           [:div 
                                            (-> vendor :vendor/address :address/street2)] " "
                                           [:div
                                            (-> vendor :vendor/address :address/city) " "
                                            (-> vendor :vendor/address :address/state) ","
                                            (-> vendor :vendor/address :address/zip)]]
                                          [:p.text-sm.italic.text-gray-400 "No address"]))}
                      {:key      "paid"
                       :name     "Paid"
                       :sort-key "paid"
                       :render   (fn [[_ _ paid]]
                                   (com/pill {:class "text-xs font-medium"
                                              :color :primary}
                                             "Paid $" (Math/round paid)))}]}))



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

(defn vendor-save [{:keys [form-params identity route-params query-params request-method] :as request
                    {:keys [vendor-id]} :route-params
                    {:keys [client-id]} :query-params}]


  (assert-can-see-client identity client-id)

  @(dc/transact conn [[:upsert-entity (-> form-params
                                          (assoc :db/id (:vendor-id route-params))
                                          (update :vendor/address (fn [a]
                                                                    (if (or (:address/street1 a)
                                                                            (:address/street2 a)
                                                                            (:address/city a)
                                                                            (:address/state a)
                                                                            (:address/zip a)
                                                                            (:db/id a))
                                                                      a
                                                                      nil)) ))]])
  (html-response 

    (row* identity [(dc/pull (dc/db conn) [:db/id :client/code] client-id)
                    (dc/pull (dc/db conn) vendor-read vendor-id)
                    (sum-for-client-vendor client-id vendor-id)
                    ] {:flash? true})
    :headers {"hx-trigger"  "modalclose"
              "hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" vendor-id)}))

(def default-vendor-read '[* {[:vendor/legal-entity-1099-type :xform iol-ion.query/ident] [:db/ident]
                              [:vendor/legal-entity-tin-type :xform iol-ion.query/ident]  [:db/ident]}])


(def form-schema (mc/schema [:map
                             [:vendor/address {:default {}}
                              [:maybe
                               [:map 
                                [:db/id {:optional true} [:maybe entity-id]]
                                [:address/street1 {:optional true} [:maybe [:string {:decode/string strip}]]]
                                [:address/street2 {:optional true} [:maybe [:string {:decode/string strip}]]]
                                [:address/city {:optional true} [:maybe [:string {:decode/string strip}]]]
                                [:address/state {:optional true} [:maybe [:string {:decode/string strip}]]]
                                [:address/zip {:optional true} [:maybe [:re { :error/message "invalid zip"
                                                                             :decode/string strip} #"^(\d{5}|)$"]]]]]]
                             [:vendor/legal-entity-name {:optional true} [:maybe [:string {:decode/string strip}]]]
                             [:vendor/legal-entity-first-name {:optional true} [:maybe [:string {:decode/string strip}]]]
                             [:vendor/legal-entity-middle-name {:optional true} [:maybe [:string {:decode/string strip}]]]
                             [:vendor/legal-entity-last-name {:optional true} [:maybe [:string {:decode/string strip}]]]
                             [:vendor/legal-entity-tin {:optional true} [:maybe [:string {:decode/string strip}]]]
                             [:vendor/legal-entity-tin-type {:optional true} [:maybe (ref->enum-schema "legal-entity-tin-type")]]
                             [:vendor/legal-entity-1099-type {:optional true} [:maybe (ref->enum-schema "legal-entity-1099-type")]]]))

(defn vendor-dialog [{{:keys [client-id]} :query-params {:keys [vendor-id]} :route-params :keys [entity form-params form-errors]}]
  (fc/start-form (or (when (seq form-params)
                       form-params)
                     (when entity
                       (mc/decode form-schema entity main-transformer))
                     {})
      form-errors
    (modal-response 
      (com/modal
        {}
        [:form {:hx-post (url (bidi/path-for ssr-routes/only-routes
                                             :company-1099-vendor-save
                                             :request-method :post
                                             :vendor-id vendor-id)
                              {:client-id client-id})
                :class   "w-full h-full max-w-2xl"
                :hx-swap       "outerHTML swap:300ms"}

         [:fieldset {:class "hx-disable w-full h-full"}
          (com/modal-card
            {}
            [:div.flex [:div.p-2 "Vendor 1099 Info"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:vendor/name entity)]]
            [:div.grid.grid-cols-6.gap-x-4.gap-y-2
             
             (fc/with-field-default :vendor/address {}
               (println "ADDRESS" fc/*current*)
               (list [:h4.text-xl.border-b.col-span-6 "Address"]
                     [:div.col-span-6
                      (fc/with-field :db/id
                        (com/hidden {:name (fc/field-name)
                                     :value (fc/field-value)}))

                      (fc/with-field :address/street1
                        (com/validated-field {:label  "Street 1"
                                              :errors (fc/field-errors)}
                                             (com/text-input {:name        (fc/field-name)
                                                              :class "w-full"
                                                              :value       (fc/field-value)
                                                              :placeholder "1700 Pennsylvania Ave"
                                                              :autofocus   true})))]
                     [:div.col-span-6
                      (fc/with-field :address/street2
                        (com/validated-field {:label  "Street 2"
                                              :errors (fc/field-errors)}
                                             (com/text-input {:name        (fc/field-name)
                                                              :class "w-full"
                                                              :value       (fc/field-value)
                                                              :placeholder "Suite 200"})))]
                     [:div.col-span-3
                      (fc/with-field :address/city
                        (com/validated-field {:label  "City"
                                              :errors (fc/field-errors)}
                                             (com/text-input {:name        (fc/field-name)
                                                              :class "w-full"
                                                              :value       (fc/field-value)
                                                              :placeholder "Cupertino"})))]
                     [:div.col-span-1
                      (fc/with-field :address/state
                        (com/validated-field {:label  "State"
                                              :errors (fc/field-errors)}
                                             (com/text-input {:name        (fc/field-name)
                                                              :class "w-full"
                                                              :value       (fc/field-value)
                                                              :placeholder "CA"})))]
                     [:div.col-span-2
                      (fc/with-field :address/zip
                        (com/validated-field {:label  "Zip"
                                              :errors (fc/field-errors)}
                                             (com/text-input {:name        (fc/field-name)
                                                              :class "w-full"
                                                              :value       (fc/field-value)
                                                              :placeholder "98102"})))]))
             
             [:h4.text-xl.border-b.col-span-6 "Legal Entity"]
             [:div.col-span-6
              (fc/with-field :vendor/legal-entity-name 
                (com/validated-field {:label  "Legal Entity Name"
                            :errors (fc/field-errors)}
                           (com/text-input {:name        (fc/field-name)
                                            :class "w-full"
                                            :value       (fc/field-value)
                                            :placeholder "Good Restaurant LLC"})))]
             [:div.col-span-6.text-center " - OR -"]
             [:div.col-span-2
              (fc/with-field :vendor/legal-entity-first-name
                (com/validated-field {:label  "First Name"
                            :errors (fc/field-errors)}
                           (com/text-input {:name        (fc/field-name)
                                            :value       (fc/field-value)
                                            :placeholder "John"})))]
             [:div.col-span-2
              (fc/with-field :vendor/legal-entity-middle-name
                (com/validated-field {:label  "Middle Name"
                            :errors (fc/field-errors)}
                           (com/text-input {:name        (fc/field-name)
                                            :value       (fc/field-value)
                                            :placeholder "C."})))]
             [:div.col-span-2
              (fc/with-field :vendor/legal-entity-last-name
                (com/validated-field {:label  "Last Name"
                            :errors (fc/field-errors)}
                           (com/text-input {:name        (fc/field-name)
                                            :value       (fc/field-value)
                                            :placeholder "Riley"})))]
             [:div.col-span-2
              (fc/with-field :vendor/legal-entity-tin
                (com/validated-field {:label  "TIN"
                            :errors (fc/field-errors)}
                           (com/text-input {:name        (fc/field-name)
                                            :value       (fc/field-value)
                                            :placeholder "John"})))]
             [:div.col-span-2
              (fc/with-field :vendor/legal-entity-tin-type
                (com/validated-field {:label  "TIN Type"
                            :errors (fc/field-errors)}
                           (com/select {:name         (fc/field-name)
                                        :allow-blank? true
                                        :value        (some-> (fc/field-value) name)
                                        :options      [["ein" "EIN"]
                                                       ["ssn" "SSN"]]})))]
             [:div.col-span-2
              (fc/with-field :vendor/legal-entity-1099-type
                (com/validated-field {:label  "1099 Type"
                            :errors (fc/field-errors)}
                           (com/select {:name         (fc/field-name)
                                        :allow-blank? true
                                        :value        (some-> (fc/field-value) name)
                                        :options (ref->select-options "legal-entity-1099-type")})))]]
            [:div
             (com/form-errors {:errors (:errors fc/*form-errors*)})
             (com/validated-save-button {:errors form-errors} "Save vendor")])]]))))

(def vendor-table (helper/table-route grid-page))
(def page (helper/page-route grid-page))

(def key->handler
  (apply-middleware-to-all-handlers
   (->>
    {:company-1099               page
     :company-1099-vendor-table  vendor-table
     :company-1099-vendor-dialog (-> vendor-dialog
                                     (wrap-entity [:route-params :vendor-id] default-vendor-read)
                                     (wrap-schema-enforce :route-schema [:map [:vendor-id entity-id]]
                                                          :query-schema [:map [:client-id entity-id]]))
     :company-1099-vendor-save   (-> vendor-save
                                     (wrap-entity [:form-params :db/id] default-vendor-read)
                                     (wrap-schema-enforce :form-schema form-schema
                                                          :route-schema [:map [:vendor-id entity-id]]
                                                          :query-schema [:map [:client-id entity-id]])
                                     (wrap-nested-form-params)
                                     (wrap-form-4xx-2 (-> vendor-dialog
                                                          (wrap-entity [:form-params :db/id] default-vendor-read)
                                                          (wrap-entity [:route-params :vendor-id] default-vendor-read)
                                                          (wrap-schema-enforce :route-schema [:map [:vendor-id entity-id]]
                                                                               :query-schema [:map [:client-id entity-id]]))))})
   (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)))))
