(ns auto-ap.ezcater-test
  (:require
   [auto-ap.ezcater.core :as sut]
   [auto-ap.integration.util :refer [wrap-setup]]
   [auto-ap.utils :refer [dollars=]]
   [clojure.test :as t]
   [auto-ap.time-reader]))

(t/use-fixtures :each wrap-setup)

(def sample-event {"id"          "bf3dcf5c-a68f-42d9-9084-049133e03d3d",
                   "parent_type" "Caterer",
                   "parent_id"   "91541331-d7ae-4634-9e8b-ccbbcfb2ce70",
                   "entity_type" "Order",
                   "entity_id"   "9ab05fee-a9c5-483b-a7f2-14debde4b7a8",
                   "key"         "accepted",
                   "occurred_at" "2022-07-21T19:21:07.549Z"})

(def known-order
  {:uuid            "9ab05fee-a9c5-483b-a7f2-14debde4b7a8",
   :client-code "ABC", :client-location "DT"
   :orderNumber "ZX7156"
   :orderSourceType "MARKETPLACE",
   :caterer
   {:name    "Nick The Greek",
    :uuid    "91541331-d7ae-4634-9e8b-ccbbcfb2ce70",
    :address {:street "165 Plaza Dr"}},
   :event
   {:timestamp              "2022-07-21T19:15:00Z",
    :catererHandoffFoodTime "2022-07-21T19:15:00Z",
    :orderType              "TAKEOUT"},
   :catererCart
   {:orderItems
    [{:name            "Spartan Package",
      :quantity        10,
      :posItemId       nil,
      :totalInSubunits {:currency "USD", :subunits 20950}}
     {:name            "Spartan Package",
      :quantity        10,
      :posItemId       nil,
      :totalInSubunits {:currency "USD", :subunits 20950}}],
    :totals           {:catererTotalDue 420.65},
    :feesAndDiscounts []},
   :totals
   {:customerTotalDue          {:currency "USD", :subunits 45409},
    :pointOfSaleIntegrationFee {:currency "USD", :subunits 0},
    :tip                       {:currency "USD", :subunits 0},
    :salesTax                  {:currency "USD", :subunits 3509},
    :salesTaxRemittance        {:currency "USD", :subunits 0},
    :subTotal                  {:currency "USD", :subunits 41900}}})

(t/deftest lookup-order
  (t/testing "It should find the order from ezcater"
    (with-redefs [sut/get-caterer (fn [k]
                                    (t/is (= k "91541331-d7ae-4634-9e8b-ccbbcfb2ce70"))
                                    {
                                     :ezcater-integration/_caterers {:ezcater-integration/api-key "bmlrdHNpZ2FyaXNAZ21haWwuY29tOmQwMzQwMjYzOWI2ODQxNmVkMjdmZWYxMWFhZTk3YzU1MDlmNTcyNjYwMDAzOTA5MDE2OGMzODllNDBjNTVkZGE"}
                                     :ezcater-location/_caterer [{:ezcater-location/location "DT"
                                                                  :client/_ezcater-locations {:client/code "ABC"}}]
                                     })]
      (t/is (= known-order
               (sut/lookup-order sample-event))))))

(t/deftest order->sales-order
  (t/testing "It should use the date"
    (t/is (= #clj-time/date-time "2022-01-01T00:00:00-08:00"
           (-> known-order
               (assoc-in [:event :timestamp]
                         "2022-01-01T08:00:00Z")
               (sut/order->sales-order)
               (:sales-order/date ))))
    (t/is (= #clj-time/date-time "2022-06-01T00:00:00-07:00"
             (-> known-order
                 (assoc-in [:event :timestamp]
                           "2022-06-01T07:00:00Z")
                 (sut/order->sales-order)
                 (:sales-order/date )))))
  (t/testing "It should simulate a single line item for everything"
    (t/is (= 1
             (-> known-order
                 sut/order->sales-order
                 :sales-order/line-items
                 count)))
    (t/is (= #{"EZCater Catering"}
             (->> known-order
                 sut/order->sales-order
                 :sales-order/line-items
                 (map :order-line-item/category)
                 set))))

  (t/testing "It should generate an external-id"
    (t/is (= "ezcater/order/ABC-DT-9ab05fee-a9c5-483b-a7f2-14debde4b7a8"
             (:sales-order/external-id (sut/order->sales-order known-order)))))
  

  (t/testing "Should capture amounts"
    (t/is (= 35.09 (-> known-order
                       sut/order->sales-order
                       :sales-order/tax)))
    (t/is (= 0.0 (-> known-order
                       sut/order->sales-order
                       :sales-order/tip))))
  (t/testing "Should calculate 7% commision on ezcater orders"
    (t/is (dollars= 7.0 
             (-> known-order
                 (assoc :orderSourceType "EZCATER")
                 (assoc-in [:totals :subTotal :subunits] 10000)
                 sut/commision)))
    (t/testing "Should inlclude delivery fee in commision"
      (t/is (dollars= 14.0 
               (-> known-order
                   (assoc :orderSourceType "EZCATER")
                   (assoc-in [:totals :subTotal :subunits] 10000)
                   (assoc-in [:catererCart :feesAndDiscounts 0 :cost :subunits] 10000)
                   sut/commision)))))
  (t/testing "Should calculate 15% commision on marketplace orders"
    (t/is (dollars= 15.0 
             (-> known-order
                 (assoc :orderSourceType "MARKETPLACE")
                 (assoc-in [:totals :subTotal :subunits] 10000)
                 sut/commision)))
    (t/testing "Should inlclude delivery fee in commision"
      (t/is (dollars= 30.0 
               (-> known-order
                   (assoc :orderSourceType "MARKETPLACE")
                   (assoc-in [:totals :subTotal :subunits] 10000)
                   (assoc-in [:catererCart :feesAndDiscounts 0 :cost :subunits] 10000)
                   sut/commision)))))
  (t/testing "Should calculate 2.75% ccp fee"
    (t/is (dollars= 8.97
                    (-> known-order
                        (assoc :orderSourceType "MARKETPLACE")
                        (assoc-in [:totals :subTotal :subunits] 10000)
                        (assoc-in [:totals :salesTax :subunits] 10000)
                        (assoc-in [:catererCart :feesAndDiscounts 0 :cost :subunits] 10000)
                        sut/ccp-fee))))
  (t/testing "Should use ezcater total paid to the customer"
    (t/is (dollars= 454.09
                    (-> known-order
                        sut/order->sales-order
                       :sales-order/total))))
  (t/testing "Should derive adjustments food-total + sales-tax - caterer-total - service fee - ccp fee"
    (t/is (dollars= -42.99
                    (-> known-order
                        sut/order->sales-order
                        :sales-order/discount))))

  (t/testing "Should create a charge for the order"
    (t/is (dollars= 454.09
                    (-> known-order
                        sut/order->sales-order
                        :sales-order/charges
                        first
                        :charge/total)))))


