(ns ezcater-xls
  (:require
   [auto-ap.datomic :refer [conn]]
   [auto-ap.time :as atime]
   [clj-time.coerce :as coerce]
   [datomic.api :as dc]
   [clojure.data.json :as json]
   [dk.ative.docjure.spreadsheet :as doc]
   [auto-ap.parse :as parse]
   [com.brunobonacci.mulog :as mu]
   [auto-ap.logging :as alog]
   [clojure.java.io :as io]))

(defn fmt-amount [a]
  (with-precision 2
    (some-> a
            bigdec
            (.setScale 2 java.math.RoundingMode/HALF_UP)
            (double))))

(defn extract-sheet-details [f]
  (into []
        (for [row (->> (doc/load-workbook f)
                       (doc/sheet-seq)
                       first
                       (doc/row-seq)
                       )]
          (mapv doc/read-cell (doc/cell-seq row))
          )))

(defn rows->maps [rows]
  (let [[headers & rows] rows]
    (for [r rows]
      (into {}
            (map vector headers r)))))


(defn map->sales-order [r clients]
  (let [order-number (get r "Order Number")
        event-date   (get r "Event Date")
        store-name   (get r "Store Name")
        adjustments (get r "Adjustments")
        tax (get r "Sales Tax")
        food-total (get r "Food Total")
        commission (get r "Commission")
        fee (get r "Payment Transaction Fee")
        tip (get r "Tip")
        caterer-name (get r "Caterer Name")
        client (some->> caterer-name
                        (parse/exact-match clients))
        client-id (:db/id client)
        location (first (:client/locations client))]
    (if (and event-date client-id location) 
      #:sales-order
      {:date           (atime/unparse-local (atime/localize (coerce/to-date-time event-date)) atime/iso-date)
       :order-number order-number
       :external-id    (str "ezcater/order/" client-id "-" location "-" order-number)
       :client         client
       :location       location
       :reference-link (str order-number)
       :line-items     [#:order-line-item
                        {:external-id (str "ezcater/order/" client-id "-" location "-" order-number "-" 0)
                         :item-name   "EZCater Catering"
                         :category    "EZCater Catering"
                         :discount    (fmt-amount (or adjustments 0.0))
                         :tax         (fmt-amount tax)
                         :total       (fmt-amount (+ food-total
                                                     tax
                                                     tip))}]

       :charges     [#:charge
                     {:type-name   "CARD"
                      :date        (atime/unparse-local (atime/localize (coerce/to-date-time event-date)) atime/iso-date)
                      :client      client-id
                      :location    location
                      :external-id (str "ezcater/charge/" client-id "-" location "-" order-number "-" 0)
                      :processor   :ccp-processor/ezcater
                      :total       (fmt-amount (+ food-total
                                                  tax
                                                  tip
                                                  ))
                      :tip         (fmt-amount tip)}]
       :total          (fmt-amount (+ food-total
                                      tax))
       :discount (fmt-amount (or adjustments 0.0))
       :service-charge (fmt-amount (+ fee commission))
       :tax (fmt-amount tax)
       :tip (fmt-amount tip)
       :returns 0.0
       :vendor :vendor/ccp-ezcater
       }
      (alog/warn ::missing-client
                 :order order-number
                 :store-name store-name 
                 :caterer-name caterer-name))))

(defn stream->sales-orders [s]
  (let [clients (map first (dc/q '[:find (pull ?c [:client/code
                                                   :db/id
                                                   :client/feature-flags
                                                   {:client/location-matches [:location-match/matches :location-match/location]}
                                                   :client/name
                                                   :client/matches
                                                   :client/locations])
                                   :where [?c :client/code]]
                                 (dc/db conn)))]
    (into []
          (->> s
               extract-sheet-details
               rows->maps
               (map #(map->sales-order % clients))
               (filter identity)))))

(defn import-stuff []
  (with-open [s (io/input-stream "/home/brycecovert/Downloads/test_2023-04-01_2023-04-30_2023-05-04.xlsx")]
    (stream->sales-orders s)))


