;; lib/dream/tests/api.sx — facade: app builders + default stack.

(define dream-ap-pass 0)
(define dream-ap-fail 0)
(define dream-ap-fails (list))

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

(dream-ap-test "version is a string" (string? dream-version) true)

;; ── dream-make-app: routes -> handler with default stack ───────────
(define
  dream-ap-routes
  (list
    (dream-get "/" (fn (req) (dream-html "<h1>hi</h1>")))
    (dream-get "/boom" (fn (req) (error "kaboom")))
    (dream-get
      "/raw"
      (fn (req) (dream-response 200 {} "plain words")))))
(define dream-ap-app (dream-make-app dream-ap-routes))

(dream-ap-test
  "app serves"
  (dream-resp-body (dream-ap-app (dream-request "GET" "/" {} "")))
  "<h1>hi</h1>")
(dream-ap-test
  "app catches errors -> 500"
  (dream-status (dream-ap-app (dream-request "GET" "/boom" {} "")))
  500)
(dream-ap-test
  "app 404 for unknown"
  (dream-status (dream-ap-app (dream-request "GET" "/nope" {} "")))
  404)
(dream-ap-test
  "app sniffs content-type"
  (dream-resp-header
    (dream-ap-app (dream-request "GET" "/raw" {} ""))
    "content-type")
  "text/plain; charset=utf-8")

;; ── dream-make-app-with: extra outer middleware ────────────────────
(define
  dream-ap-tag
  (fn (next) (fn (req) (dream-add-header (next req) "X-App" "1"))))
(define
  dream-ap-app2
  (dream-make-app-with (list dream-ap-tag) dream-ap-routes))
(dream-ap-test
  "extra middleware header"
  (dream-resp-header
    (dream-ap-app2 (dream-request "GET" "/" {} ""))
    "x-app")
  "1")

;; ── dream-serve wires through dream-run ────────────────────────────
(define dream-ap-captured nil)
(define dream-ap-listen (fn (op) (begin (set! dream-ap-captured op) :ok)))
(define
  dream-ap-served
  (dream-run-with dream-ap-listen (dream-make-app dream-ap-routes) {:port 7000}))
(dream-ap-test "serve listens" dream-ap-served :ok)
(dream-ap-test "serve port" (get dream-ap-captured :port) 7000)
(dream-ap-test
  "served app runs"
  (get ((get dream-ap-captured :app) {:method "GET" :target "/"}) :body)
  "<h1>hi</h1>")

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