;; lib/commerce/tests/integration.sx — end-to-end composition proof.
;; Uses (commerce-test name got expected) provided by conformance.sh.
;;
;; One narrative across every module: catalog → stock check → quote
;; (promo+stack+tax) → order flow → payment envelope → settle → recon → refund.
;; Proves the seams tie together with consistent numbers (the project's thesis:
;; minikanren pricing + flow lifecycle + persist ledger compose).
;; Builds one flow env with BOTH the order and refund flows.

(define env (order-make-env))
(define _rf (refund-flow-load! env))
(define b (persist/mem-backend))

(define
  cat
  (make-catalog
    (list
      (list "widget" 1000 :standard)
      (list "book" 800 :zero-rated))
    (list (list "widget" :small -200))
    (list (list "widget" :small 10) (list "book" :none 5))))

(define
  rules
  (list
    (list :uk :standard :guest 2000)
    (list :uk :zero-rated :guest 0)))

(define ctx (make-pricing-context cat rules :uk :guest))

(define
  ruleset
  (list
    (list :percent "TEN" :standard 1000)
    (list :fixed "FIVE" 0 50)))

;; widget :small x2 → unit 800, extended 1600 (standard); book x1 → 800 (zero-rated)
(define
  cart
  (list (list "widget" :small 2) (list "book" :none 1)))

;; 1. stock gating passes (widget:small 10 >= 2)
(commerce-test "int-can-reserve" (can-reserve? cat cart) true)

;; 2. quote ties the whole pricing pipeline together
;;    subtotal 2400; discount TEN 160 + FIVE 50 = 210; tax 1600@20% = 320;
;;    total 2400 - 210 + 320 = 2510
(define q (cart-quote ctx cart ruleset (list)))
(commerce-test "int-quote-subtotal" (quote-subtotal q) 2400)
(commerce-test "int-quote-discount" (quote-discount q) 210)
(commerce-test "int-quote-tax" (quote-tax q) 320)
(commerce-test "int-quote-total" (quote-total q) 2510)

;; 3. attribution explains where the discount landed
(commerce-test
  "int-attribution"
  (codes-for-line ctx cart ruleset (list "widget" :small 2))
  (list "TEN"))
(commerce-test
  "int-order-level"
  (order-level-codes ctx cart ruleset)
  (list "FIVE"))

;; 4. order carries the quote total into the ledger; suspends at payment
(define oid "INT-1")
(define id (order-begin! env b oid 1000 q))
(commerce-test "int-order-total-from-quote" (order-total b oid) 2510)
(commerce-test "int-waiting-payment" (order-flow-waiting env id) "payment")

;; 5. the payment envelope reflects the quoted total
(commerce-test
  "int-payment-envelope"
  (payment-request b oid :GBP "https://shop/return")
  {:order "INT-1" :amount 2510 :return-url "https://shop/return" :currency :GBP})

;; 6. settle the quoted amount → reconciles exactly
(commerce-test
  "int-settled"
  (order-settle! env b id oid "pay-int" 1002 2510)
  :settled)
(commerce-test "int-status-fulfilled" (order-status b oid) :fulfilled)
(commerce-test "int-recon-ok" (order-recon b oid) :ok)

;; 7. partial refund via its own flow → recon moves to underpaid
(define rid (refund-begin! env b oid "rf-int" 2000 510))
(commerce-test "int-refund-approve" (refund-approve! env rid) :approved)
(commerce-test
  "int-refund-settle"
  (refund-settle! env b rid oid "rf-int" 2001 510)
  :settled)
(commerce-test
  "int-refunded-amount"
  (order-refunded-amount-of (order-events b oid))
  510)
(commerce-test "int-recon-after-refund" (order-recon b oid) :underpaid)

;; 8. ledger reconciliation flags the now-mismatched order
(commerce-test
  "int-mismatch"
  (mismatched-orders b)
  (list (order-stream "INT-1")))

;; 9. distinct flow ids for the order and the refund
(commerce-test "int-distinct-flow-ids" (not (= id rid)) true)
