(ns auto-ap.utils
  #?@
  (:clj
   [(:require [com.unbounce.dogstatsd.core :as statsd]
              [com.brunobonacci.mulog :as mu]
              [auto-ap.logging :as alog])]))

#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn by
  ([f xs]
   (by f identity xs))
  ([f fv xs]
   (reduce
    #(assoc %1 (f %2) (fv %2))
    {}
    xs)))

#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn replace-by [xs f x]
  (let [found? (atom false)
        replaced (mapv
                  (fn [t]
                    (if (= (f t) (f x))
                      (do (reset! found? true)
                          x)
                      t))
                  xs)]
    (if @found?
      replaced
      (into [x] replaced))))

#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn dollars-0? [amt]
  (< -0.001 amt  0.001))

#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn dollars= [amt1 amt2]
  (dollars-0? (- amt1 amt2) ))

#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn deep-merge [v & vs]
  (letfn [(rec-merge [v1 v2]
            (if (and (map? v1) (map? v2))
              (merge-with deep-merge v1 v2)
              v2))]
    (if (some identity vs)
      (reduce #(rec-merge %1 %2) v vs)
      (last vs))))

#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(def default-pagination-size 25)

#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn allow-once [f]
  (let [in-progress? (atom false)]
    (fn []
      (when (= false @in-progress?)
        (try 
          (reset! in-progress? true)
          (f)
          (finally
            (reset! in-progress? false)))))))


#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn heartbeat [f id]
  (fn []
    #?(:clj (mu/with-context {:source id}
              (try 
                (alog/info ::starting-process :id id)
                (f)
                (alog/info ::ending-process  :id id)
                (statsd/service-check {:name   (str id)
                                       :status :ok}
                                      nil)
                (catch Exception e
                  (alog/error ::process-failed :error e)
                  (statsd/service-check {:name   (str id)
                                         :status :critical}
                                        nil))))

       :cljs (do (println "Heartbeat for " id)
                 (f)))))

(defn or-0 [x]
  (if (nil? x)
    0.0
    x))