(ns auto-ap.server
  (:require
   [auto-ap.handler :refer [app]]
   [auto-ap.jobs.restore-from-backup :as job-restore-from-backup]
   [auto-ap.jobs.bulk-journal-import :as job-bulk-journal-import]
   [auto-ap.jobs.close-auto-invoices :as job-close-auto-invoices]
   [auto-ap.jobs.ezcater-upsert :as job-ezcater-upsert]
   [auto-ap.jobs.import-uploaded-invoices :as job-import-uploaded-invoices]
   [auto-ap.jobs.intuit :as job-intuit]
   [auto-ap.jobs.ntg :as job-ntg]
   #_[auto-ap.backup :as backup]
   [auto-ap.jobs.ledger-reconcile :as job-reconcile-ledger]
   [auto-ap.jobs.load-historical-sales :as job-load-historical-sales]
   [auto-ap.jobs.plaid :as job-plaid]
   [auto-ap.jobs.register-invoice-import :as job-register-invoice-import]
   [auto-ap.jobs.sales-summaries :as job-sales-summaries]
   [auto-ap.jobs.square :as job-square]
   [auto-ap.jobs.sysco :as job-sysco]
   [auto-ap.jobs.vendor-usages :as job-vendor-usages]
   [auto-ap.jobs.yodlee2 :as job-yodlee2]
   [auto-ap.logging :as alog]
   [com.unbounce.dogstatsd.core :as statsd]
   [config.core :refer [env]]
   [mount.core :as mount]
   [nrepl.server :refer [start-server]]
   [ring.adapter.jetty :refer [run-jetty]]
   [yang.scheduler :as scheduler]
   [auto-ap.jobs.insight-outcome-recommendation :as insight-outcome-recommendation])
  (:import
   (org.eclipse.jetty.server.handler StatisticsHandler)
   (org.eclipse.jetty.server.handler.gzip GzipHandler)))

(defn add-shutdown-hook! [^Runnable f]
  (.addShutdownHook (Runtime/getRuntime)
                    (Thread. f)))

(defn gzip-handler []
  (let [gz (GzipHandler.)]
    (doto gz
      (.setIncludedMethods (into-array ["GET" "POST" "PUT" "DELETE" "PATCH"]))
      (.setIncludedMimeTypes (into-array ["text/css"
                                          "text/*"
                                          "text/plain"
                                          "text/javascript"
                                          "text/csv"
                                          "text/html"
                                          "text/html;charset=utf-8"
                                          "application/javascript"
                                          "application/csv"
                                          "application/edn"
                                          "application/json"
                                          "image/svg+xml"]))
      (.setMinGzipSize 1024))
    gz))

(defn configure-jetty [server]
  (let [stats-handler (StatisticsHandler.)
        gzip-handler (gzip-handler)
        default-handler (.getHandler server)]

    (.setHandler gzip-handler default-handler)
    (.setHandler stats-handler gzip-handler)
    (.setHandler server stats-handler))
  (.setStopAtShutdown server true))

(mount/defstate port :start (Integer/parseInt (str (or (env :port) "3000"))))

(mount/defstate jetty
  :start (run-jetty app {:port port
                         :join? false
                         :configurator configure-jetty
                         :response-header-size 16384
                         :request-header-size 16384})
  :stop (.stop jetty))

(defn collect-jetty-stats []
  (try
    (statsd/gauge "requests.active" (double (.getRequestsActive (.getHandler jetty))))
    (statsd/gauge "requests.1xx" (double (.getResponses1xx (.getHandler jetty))))
    (statsd/gauge "requests.2xx" (double (.getResponses2xx (.getHandler jetty))))
    (statsd/gauge "requests.3xx" (double (.getResponses3xx (.getHandler jetty))))
    (statsd/gauge "requests.4xx" (double (.getResponses4xx (.getHandler jetty))))
    (statsd/gauge "requests.5xx" (double (.getResponses5xx (.getHandler jetty))))
    (.statsReset (.getHandler jetty))
    (catch Exception e
      (alog/warn ::cant-collect-stats :error  e))))

#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(mount/defstate jetty-stats
  :start (scheduler/every (* 1000 10) collect-jetty-stats)
  :stop (scheduler/stop jetty-stats))

(defn shutdown-mount []
  (mount/stop))

(defn -main [& _]
  (let [job (System/getenv "INTEGREAT_JOB")]
    (println "JOB is" job)
    (cond (= job "square-import-job")
          (job-square/-main)

          (= job "reconcile-ledger")
          (job-reconcile-ledger/-main)

          (= job "yodlee2")
          (job-yodlee2/-main)

          (= job "yodlee2-accounts")
          (job-yodlee2/accounts-only)

          (= job "plaid")
          (job-plaid/-main)

          (= job "intuit")
          (job-intuit/-main)

          (= job "vendor-usages")
          (job-vendor-usages/-main)

          (= job "import-uploaded-invoices")
          (job-import-uploaded-invoices/-main)

          (= job "sysco")
          (job-sysco/-main)

          (= job "close-auto-invoices")
          (job-close-auto-invoices/-main)

          (= job "sales-summaries")
          (job-sales-summaries/-main)

          (= job "ezcater-upsert")
          (job-ezcater-upsert/-main)

          (= job "register-invoice-import")
          (job-register-invoice-import/-main)

          (= job "load-historical-sales")
          (job-load-historical-sales/-main)

          (= job "bulk-journal-import")
          (job-bulk-journal-import/-main)

          (= job "restore-from-backup")
          (job-restore-from-backup/-main)

          (= job "insight-outcome-recommendation")
          (insight-outcome-recommendation/-main)

           ;; (= job "export-backup")
           ;; (backup/-main)

          (= job "ntg")
          (job-ntg/-main)

          :else
          (do
            (add-shutdown-hook! shutdown-mount)
            (start-server :port 9000 :bind "0.0.0.0" #_#_:handler (cider-nrepl-handler))
            (mount/start)
            #_(alter-var-root #'nrepl.middleware.print/*print-fn* (constantly clojure.pprint/pprint))))))

