;; lib/mod/tests/pipeline.sx — Ext 19: end-to-end triage orchestration.

(define mod-pp-count 0)
(define mod-pp-pass 0)
(define mod-pp-fail 0)
(define mod-pp-failures (list))

(define
  mod-pp-test!
  (fn
    (name got expected)
    (begin
      (set! mod-pp-count (+ mod-pp-count 1))
      (if
        (= got expected)
        (set! mod-pp-pass (+ mod-pp-pass 1))
        (begin
          (set! mod-pp-fail (+ mod-pp-fail 1))
          (append!
            mod-pp-failures
            (str name "\n    expected: " expected "\n    got:      " got)))))))

(mod/policies-reset!)
(mod/register-policy!
  "market"
  (mod/ruleset
    (mod/defrule "market-spam-remove" :remove (list :classification "spam"))
    (mod/defrule "default-keep" :keep)))

;; ── spam in the market domain: full bundle ──

(define mod-pp-spam (mod/mk-report "r1" "u" "bob" "this is spam"))
(define
  mod-pp
  (mod/triage-pipeline "market" mod-pp-spam (list mod-pp-spam) "inst.example"))

(mod-pp-test!
  "pipeline action (market policy → remove)"
  (mod/pipeline-action mod-pp)
  "remove")
(mod-pp-test! "pipeline rule" (get mod-pp :rule) "market-spam-remove")
(mod-pp-test!
  "pipeline explanation mentions the action"
  (mod/str-contains? (get mod-pp :explanation) "remove")
  true)
(mod-pp-test!
  "pipeline activity is Delete (remove)"
  (get (mod/pipeline-activity mod-pp) :type)
  "Delete")
(mod-pp-test!
  "pipeline activity object is the report"
  (get (mod/pipeline-activity mod-pp) :object)
  "r1")
(mod-pp-test!
  "pipeline wire round-trips to the same action"
  (get (mod/wire->decision (mod/pipeline-wire mod-pp)) :action)
  "remove")

;; ── same report, blog domain (default) → hide, Flag ──

(define
  mod-pp-blog
  (mod/triage-pipeline "blog" mod-pp-spam (list mod-pp-spam) "inst.example"))
(mod-pp-test!
  "blog default policy → hide"
  (mod/pipeline-action mod-pp-blog)
  "hide")
(mod-pp-test!
  "blog activity is Flag"
  (get (mod/pipeline-activity mod-pp-blog) :type)
  "Flag")

;; ── clean report: keep, no activity, explanation says (none) ──

(define mod-pp-clean (mod/mk-report "r2" "u" "eve" "a fine post"))
(define
  mod-pp-k
  (mod/triage-pipeline
    "market"
    mod-pp-clean
    (list mod-pp-clean)
    "inst.example"))
(mod-pp-test! "clean → keep" (mod/pipeline-action mod-pp-k) "keep")
(mod-pp-test! "keep → no activity" (mod/pipeline-activity mod-pp-k) nil)
(mod-pp-test!
  "keep explanation says no evidence"
  (mod/str-contains? (get mod-pp-k :explanation) "Evidence: (none)")
  true)
(mod-pp-test!
  "keep wire still round-trips"
  (get (mod/wire->decision (mod/pipeline-wire mod-pp-k)) :rule)
  "default-keep")

;; ── federated handoff: market decision crosses to a peer, trust-gated ──

(mod/fed-reset!)
(define mod-pp-peer-dec (mod/wire->decision (mod/pipeline-wire mod-pp)))
(mod-pp-test!
  "untrusted peer: market decision is advisory"
  (get (mod/fed-receive-decision "peerX" mod-pp-peer-dec) :applied)
  false)
(mod/grant-trust "peerY" :mod)
(mod-pp-test!
  "trusted peer: market decision applies"
  (get (mod/fed-receive-decision "peerY" mod-pp-peer-dec) :applied)
  true)
(mod-pp-test!
  "applied action is remove"
  (get (mod/fed-applied-action "r1") :action)
  "remove")

(define mod-pipeline-tests-run! (fn () {:failures mod-pp-failures :total mod-pp-count :passed mod-pp-pass :failed mod-pp-fail}))
