;; lib/flow/tests/api.sx — Phase 5: operational introspection API.

(define flow-api-pass 0)
(define flow-api-fail 0)
(define flow-api-fails (list))

(define
  flow-api-test
  (fn
    (name actual expected)
    (if
      (= actual expected)
      (set! flow-api-pass (+ flow-api-pass 1))
      (begin
        (set! flow-api-fail (+ flow-api-fail 1))
        (append! flow-api-fails {:name name :expected expected :actual actual})))))

(define flow-a (fn (src) (flow-run src)))

;; ── flow/status ─────────────────────────────────────────────────
(flow-api-test "status: unknown id" (flow-a "(flow/status 999)") "unknown")
(flow-api-test
  "status: suspended flow"
  (flow-a
    "(defflow w (lambda (x) (suspend (quote q)))) (define id (car (cdr (flow/start w 0)))) (flow/status id)")
  "suspended")
(flow-api-test
  "status: completed flow"
  (flow-a
    "(defflow w (sequence (lambda (x) (suspend (quote q))) (lambda (v) v))) (define id (car (cdr (flow/start w 0)))) (flow/resume id 5) (flow/status id)")
  "done")
(flow-api-test
  "status: cancelled flow"
  (flow-a
    "(defflow w (lambda (x) (suspend (quote q)))) (define id (car (cdr (flow/start w 0)))) (flow/cancel id) (flow/status id)")
  "cancelled")

;; ── flow/result ─────────────────────────────────────────────────
(flow-api-test
  "result: returns the value of a completed flow"
  (flow-a
    "(defflow w (sequence (lambda (x) (suspend (quote q))) (lambda (v) (list (quote got) v)))) (define id (car (cdr (flow/start w 0)))) (flow/resume id 9) (flow/result id)")
  (list "got" 9))
(flow-api-test
  "result: a still-suspended flow has no result"
  (flow-a
    "(defflow w (lambda (x) (suspend (quote q)))) (define id (car (cdr (flow/start w 0)))) (flow/result id)")
  (list "flow-error" "not-done"))
(flow-api-test
  "result: unknown id errors"
  (flow-a "(flow/result 999)")
  (list "flow-error" "no-such-flow"))

;; ── flow/list ───────────────────────────────────────────────────
(flow-api-test "list: empty store" (flow-a "(flow/list)") (list))
(flow-api-test
  "list: reports id + status for each flow (newest first)"
  (flow-a
    "(defflow w (lambda (x) (suspend (quote q)))) (flow/start w 0) (flow/start (lambda (x) (* x 2)) 5) (flow/list)")
  (list (list 2 "done") (list 1 "suspended")))

;; ── flow/pending ────────────────────────────────────────────────
(flow-api-test
  "pending: lists suspended flows with their waiting tag"
  (flow-a
    "(defflow w (lambda (x) (suspend (quote review)))) (flow/start w 0) (flow/pending)")
  (list (list 1 "review")))
(flow-api-test
  "pending: excludes completed and cancelled flows"
  (flow-a
    "(defflow w (lambda (x) (suspend (quote q)))) (defflow v (sequence (lambda (x) (suspend (quote r))) (lambda (y) y))) (define i1 (car (cdr (flow/start w 0)))) (define i2 (car (cdr (flow/start v 0)))) (define i3 (car (cdr (flow/start w 0)))) (flow/resume i2 1) (flow/cancel i3) (flow/pending)")
  (list (list 1 "q")))
(flow-api-test
  "pending: operator can drain all pending flows"
  (flow-a
    "(defflow w (sequence (lambda (x) (suspend (quote q))) (lambda (v) (* v 10)))) (flow/start w 0) (flow/start w 0) (define ps (flow/pending)) (flow/resume (car (car ps)) 1) (flow/resume (car (car (cdr ps))) 2) (flow/list)")
  (list (list 1 "done") (list 2 "done")))

(define flow-api-tests-run! (fn () {:total (+ flow-api-pass flow-api-fail) :passed flow-api-pass :failed flow-api-fail :fails flow-api-fails}))
