;; IO registry tests — defio, *io-registry*, accessor functions, io contract
(defsuite
  "io-registry-basic"
  (deftest
    "defio registers an IO operation"
    (defio
      "test-io-basic"
      :category :data
      :params ()
      :returns "string"
      :doc "Basic test op.")
    (assert (io-registered? "test-io-basic")))
  (deftest
    "io-lookup returns spec dict"
    (defio
      "test-io-lookup"
      :category :effect
      :params (x)
      :returns "nil"
      :doc "Test effect.")
    (let
      ((spec (io-lookup "test-io-lookup")))
      (assert= (get spec "name") "test-io-lookup")
      (assert= (keyword-name (get spec "category")) "effect")
      (assert= (get spec "returns") "nil")
      (assert= (get spec "doc") "Test effect.")))
  (deftest
    "io-registered? returns false for unknown"
    (assert (not (io-registered? "nonexistent-io-op"))))
  (deftest
    "io-names includes registered ops"
    (defio
      "test-io-names"
      :category :data
      :params ()
      :returns "any"
      :doc "Names test.")
    (assert (contains? (io-names) "test-io-names")))
  (deftest
    "defio returns the spec dict"
    (let
      ((result (defio "test-io-ret" :category :code :params (a b) :returns "string" :doc "Return test.")))
      (assert= (get result "name") "test-io-ret")
      (assert= (keyword-name (get result "category")) "code"))))

(defsuite
  "io-registry-kwargs"
  (deftest
    "defio parses batchable flag"
    (defio
      "test-io-batch"
      :category :code
      :params (code lang)
      :returns "string"
      :batchable true
      :doc "Batchable op.")
    (assert= (get (io-lookup "test-io-batch") "batchable") true))
  (deftest
    "defio parses cacheable flag"
    (defio
      "test-io-cache"
      :category :data
      :params ()
      :returns "list"
      :cacheable true
      :doc "Cacheable op.")
    (assert= (get (io-lookup "test-io-cache") "cacheable") true))
  (deftest
    "defio parses params list"
    (defio
      "test-io-params"
      :category :data
      :params (a b c)
      :returns "list"
      :doc "Multi param.")
    (assert= (len (get (io-lookup "test-io-params") "params")) 3)))

(defsuite
  "io-contract"
  (deftest
    "io rejects unregistered operations"
    (let
      ((caught false))
      (try-catch
        (fn () (io "totally-unknown-op-xyz"))
        (fn (err) (set! caught true)))
      (assert caught))))

(defsuite
  "io-suspension-continuation"
  (deftest
    "code after non-suspending call executes"
    (let
      ((result (list)))
      (define f (fn () (set! result (append result "a"))))
      (do (f) (set! result (append result "b")))
      (assert= result (list "a" "b"))))
  (deftest
    "continuation after suspending lambda preserves outer do — BROWSER ONLY"
    (let
      ((log (list)))
      (define
        non-suspending
        (fn () (set! log (append log "a")) (set! log (append log "b"))))
      (do (non-suspending) (set! log (append log "after-call")))
      (assert= log (list "a" "b" "after-call"))
      (assert
        true
        "passes without suspension — browser test needed for full verify: stub VM loses outer do continuation after cek_resume completes"))))
