(ns auto-ap.ssr.outgoing-invoice.new
  (:require [amazonica.aws.lambda :as lambda]
            [auto-ap.datomic :refer [conn pull-attr]]
            [auto-ap.routes.invoice :as invoice-route]
            [auto-ap.routes.outgoing-invoice :as route]
            [auto-ap.routes.utils :refer [wrap-client-redirect-unauthenticated
                                          wrap-secure]]
            [auto-ap.ssr-routes :as ssr-routes]
            [auto-ap.ssr.common-handlers :refer [add-new-entity-handler]]
            [auto-ap.ssr.components :as com]
            [auto-ap.ssr.form-cursor :as fc]
            [auto-ap.ssr.grid-page-helper :refer [wrap-trim-client-ids]]
            [auto-ap.ssr.hx :as hx]
            [auto-ap.ssr.nested-form-params :refer [wrap-nested-form-params]]
            [auto-ap.ssr.svg :as svg]
            [auto-ap.ssr.ui :refer [base-page]]
            [auto-ap.ssr.utils :refer [clj-date-schema modal-response money
                                       percentage strip wrap-schema-decode]]
            [auto-ap.time :as atime]
            [bidi.bidi :as bidi]
            [clojure.data.json :as json]
            [datomic.api :as dc]
            [malli.core :as mc]))

(def form-schema (mc/schema [:map
                             [:outgoing-invoice/client [:entity-map {:pull '[:client/name {:client/address [*]}]}]]
                             [:outgoing-invoice/date clj-date-schema]
                             [:outgoing-invoice/to :string]
                             [:outgoing-invoice/invoice-number :string]
                             [:outgoing-invoice/tax percentage]
                             [:outgoing-invoice/to-address [:map
                                                            [:street1 :string]
                                                            [:street2  {:optional true} [:maybe [:string {:decode/string strip}]]]
                                                            [:city :string]
                                                            [:state :string]
                                                            [:zip :string]]]
                             [:outgoing-invoice/line-items
                              [:vector {:coerce? true}
                               [:map
                                [:outgoing-invoice-line-item/description :string]
                                [:outgoing-invoice-line-item/unit-price money]
                                [:outgoing-invoice-line-item/quantity money]]]]]))

(defn line-item [z]
  (com/data-grid-row
   (hx/alpine-mount-then-appear {:x-data   (hx/json {:show      false})
                                 :data-key "show"
                                 :x-ref    "p"})
   (fc/with-field :db/id
     (com/hidden {:name  (fc/field-name)
                  :value (fc/field-value)}))
   (com/data-grid-cell
    {}
    (fc/with-field :outgoing-invoice-line-item/description
      (com/text-input {:name (fc/field-name)
                       :value (fc/field-value)
                       :class "w-full"
                       :placeholder "Catered sandwiches"})))
   (com/data-grid-cell
    {:class "w-8"}
    (fc/with-field :outgoing-invoice-line-item/quantity
      (com/money-input {:name (fc/field-name)
                        :value (fc/field-value)
                        :class "w-24"
                        :placeholder "20"})))
   (com/data-grid-cell
    {}
    (fc/with-field :outgoing-invoice-line-item/unit-price
      (com/money-input {:name (fc/field-name)
                        :value (fc/field-value)
                        :class "w-24"
                        :placeholder "23.50"})))
   (com/data-grid-cell {:class "align-top"}
                       (com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))

(defn form* [{:keys [form-params form-errors]}]

  (fc/start-form
   form-params
   form-errors
   [:form.flex.gap-4 {:hx-post (bidi.bidi/path-for ssr-routes/only-routes
                                                   ::route/new-submit)}

    (com/content-card {:max-w "max-w-screen-lg"}
                      [:div {:class "flex flex-col px-4 py-3 space-y-3 lg:flex-row lg:items-center lg:justify-between lg:space-y-0 lg:space-x-4 text-gray-800 dark:text-gray-100"}
                       [:div
                        [:h1.text-2xl.mb-3.font-bold "New outgoing invoice"]]
                       [:div {:class "flex flex-col flex-shrink-0 space-y-3 md:flex-row md:items-center lg:justify-end md:space-y-0 md:space-x-3"}]]
                      [:div.p-4
                       (fc/with-field :outgoing-invoice/client
                         (com/validated-field {:errors (fc/field-errors)
                                               :label "From (client)"}
                                              [:div.w-96
                                               (com/typeahead {:name        (fc/field-name)
                                                               :error?      (fc/error?)
                                                               :autofocus true
                                                               :class       "w-96"
                                                               :placeholder "Search..."
                                                               :url         (bidi/path-for ssr-routes/only-routes :company-search)
                                                               :value       (fc/field-value)
                                                               :content-fn  (fn [c] (pull-attr (dc/db conn) :client/name c))})]))

                       (fc/with-field :outgoing-invoice/invoice-number
                         (com/validated-field {:errors (fc/field-errors)
                                               :label "Invoice #"}
                                              [:div.w-96
                                               (com/text-input {:name        (fc/field-name)
                                                                :error?      (fc/error?)
                                                                :class       "w-96"
                                                                :placeholder "10000"
                                                                :value       (fc/field-value)})]))
                       (fc/with-field :outgoing-invoice/date
                         (com/validated-field {:errors (fc/field-errors)
                                               :label "Date"}
                                              [:div.w-96
                                               (com/date-input {:name        (fc/field-name)
                                                                :error?      (fc/error?)
                                                                :class       "w-96"
                                                                :placeholder "10000"
                                                                :value       (-> (fc/field-value)
                                                                                 (atime/unparse-local atime/normal-date))})]))



                       (fc/with-field-default :outgoing-invoice/line-items [{:db/id "first"}]
                         (com/validated-field {:errors (fc/field-errors)
                                               :label "Line items"}
                                              (com/data-grid {:headers [(com/data-grid-header {} "Description")
                                                                        (com/data-grid-header {} "Quantity")
                                                                        (com/data-grid-header {} "Unit Price")
                                                                        (com/data-grid-header {} "")]}
                                                             (fc/cursor-map line-item)
                                                             (com/data-grid-new-row {:colspan 4
                                                                                     :index     (count (fc/field-value))
                                                                                     :hx-get    (bidi/path-for ssr-routes/only-routes

                                                                                                               ::route/new-line-item)} "Add line"))))

                       (fc/with-field-default :outgoing-invoice/tax 10.0

                         (com/validated-field {:errors (fc/field-errors)
                                               :label "Tax %"}
                                              (com/money-input {:name (fc/field-name)
                                                                :value (fc/field-value)})))

                       [:div.flex.flex-row-reverse (com/button {:color :primary :class "w-24"} "Generate")]])
    (com/content-card {:max-w "max-w-24"}
                      [:div.p-4
                       [:h3.text-lg "Recipient details"]
                       [:div.flex.flex-col.gap-2
                        (fc/with-field :outgoing-invoice/to
                          (com/validated-field {:errors (fc/field-errors)
                                                :label "To"}
                                               [:div.w-96
                                                (com/text-input {:name        (fc/field-name)
                                                                 :error?      (fc/error?)
                                                                 :class       "w-96"
                                                                 :placeholder "Hello Company"
                                                                 :value       (fc/field-value)})]))

                        (fc/with-field-default :outgoing-invoice/to-address {}
                          (list
                           (fc/with-field :address/street1
                             (com/validated-field {:label  "Address"
                                                   :errors (fc/field-errors)}
                                                  (com/text-input {:name        (fc/field-name)
                                                                   :error?      (fc/error?)
                                                                   :class       "w-full"
                                                                   :placeholder "1200 Pennsylvania Avenue"
                                                                   :value       (fc/field-value)})))
                           (fc/with-field :address/street2
                             (com/validated-field {:errors (fc/field-errors)}
                                                  (com/text-input {:name        (fc/field-name)
                                                                   :error?      (fc/error?)
                                                                   :class       "w-full"
                                                                   :placeholder "Suite 300"
                                                                   :value       (fc/field-value)})))
                           [:div.flex.w-full.space-x-4
                            (fc/with-field :address/city
                              (com/validated-field {:errors (fc/field-errors)
                                                    :class  "w-full grow shrink"}
                                                   (com/text-input {:name        (fc/field-name)
                                                                    :error?      (fc/error?)
                                                                    :class       "w-full"
                                                                    :placeholder "Cupertino"
                                                                    :value       (fc/field-value)})))
                            (fc/with-field :address/state
                              (com/validated-field {:errors (fc/field-errors)
                                                    :class  "w-16 shrink-0"}
                                                   (com/text-input {:name        (fc/field-name)
                                                                    :error?      (fc/error?)
                                                                    :class       "w-full"
                                                                    :placeholder "CA"
                                                                    :value       (fc/field-value)})))
                            (fc/with-field :address/zip
                              (com/validated-field {:errors (fc/field-errors)
                                                    :class  "w-24 shrink-0"}
                                                   (com/text-input {:name        (fc/field-name)
                                                                    :error?      (fc/error?)
                                                                    :placeholder "98101"
                                                                    :class       "w-full"
                                                                    :value       (fc/field-value)})))]))]])]))

(defn- fmt-money [total]
  (format "$%,.2f" (or total 0)))

(defn submit [{:keys [form-params]}]
  (let [line-items (->> form-params
                        :outgoing-invoice/line-items
                        (filter (fn [li] (not-empty (:outgoing-invoice-line-item/description li))))
                        (mapv
                         #(assoc % :outgoing-invoice-line-item/total (* (:outgoing-invoice-line-item/unit-price %)
                                                                        (:outgoing-invoice-line-item/quantity %)))))

        subtotal (reduce + 0.0 (map :outgoing-invoice-line-item/total line-items))
        tax (* subtotal (:outgoing-invoice/tax form-params))
        total (+ subtotal tax)
        final-outgoing-invoice (-> form-params
                                   (assoc :outgoing-invoice/line-items
                                          line-items
                                          :outgoing-invoice/total total
                                          :outgoing-invoice/tax tax))
        result

        (-> (lambda/invoke {:function-name "genpdf" :payload
                            (json/write-str
                             (-> final-outgoing-invoice
                                 (update :outgoing-invoice/total fmt-money)
                                 (update :outgoing-invoice/tax fmt-money)
                                 (update :outgoing-invoice/line-items
                                         (fn [lis]
                                           (mapv
                                            #(-> %
                                                 (update :outgoing-invoice-line-item/total fmt-money)
                                                 (update :outgoing-invoice-line-item/unit-price fmt-money))
                                            lis)))
                                 (update :outgoing-invoice/date
                                         #(some-> % (atime/unparse-local atime/normal-date)))))})
            :payload
            slurp
            json/read-str)]
    (modal-response
     (com/modal {}
                (com/modal-card {} [:div "Download your invoice"] [:div
                                                                   "click "
                                                                   (com/link {:href (str "https://data.prod.app.integreatconsult.com/" result)}
                                                                             "here")
                                                                   " to download"] [:div])))))

(def page (-> (fn page [{:keys [identity] :as request}]
                (base-page
                 request
                 (com/page {:nav              com/main-aside-nav
                            :client-selection (:client-selection request)
                            :clients          (:clients request)
                            :client           (:client request)
                            :identity         (:identity request)
                            :request request}
                           (apply com/breadcrumbs {} [[:a {:href (bidi/path-for ssr-routes/only-routes
                                                                                ::invoice-route/all-page)}
                                                       "Invoices"]
                                                      [:a {:href "#"} ;; TODO
                                                       "Outgoing"]
                                                      [:a {:href (bidi/path-for ssr-routes/only-routes
                                                                                ::route/new)}
                                                       "New"]])
                           (form* request))
                 "New outgoing invoice"))
              (wrap-trim-client-ids)
              (wrap-secure)
              (wrap-client-redirect-unauthenticated)))

(def route->handler
  {::route/new page
   ::route/new-submit (-> submit
                          (wrap-schema-decode :form-schema form-schema)
                          (wrap-nested-form-params))
   ::route/new-line-item (->

                          (add-new-entity-handler [:outgoing-invoice/line-items]
                                                  (fn render [cursor request]
                                                    (line-item
                                                     {:value cursor }))
                                                  (fn build-new-row [base _]
                                                    base)))})