(defsuite
  "string-buffer"
  (deftest
    "make-string-buffer creates a string-buffer"
    (let ((buf (make-string-buffer))) (assert (string-buffer? buf))))
  (deftest
    "string-buffer? is false for non-buffers"
    (assert= false (string-buffer? "hello"))
    (assert= false (string-buffer? 42))
    (assert= false (string-buffer? nil))
    (assert= false (string-buffer? (list)))
    (assert= false (string-buffer? {:key "val"})))
  (deftest
    "type-of returns string-buffer"
    (assert= "string-buffer" (type-of (make-string-buffer))))
  (deftest
    "empty buffer converts to empty string"
    (let
      ((buf (make-string-buffer)))
      (assert= "" (string-buffer->string buf))))
  (deftest
    "empty buffer has length zero"
    (let
      ((buf (make-string-buffer)))
      (assert= 0 (string-buffer-length buf))))
  (deftest
    "single append accumulates string"
    (let
      ((buf (make-string-buffer)))
      (string-buffer-append! buf "hello")
      (assert= "hello" (string-buffer->string buf))))
  (deftest
    "multiple appends join in order"
    (let
      ((buf (make-string-buffer)))
      (string-buffer-append! buf "foo")
      (string-buffer-append! buf "bar")
      (string-buffer-append! buf "baz")
      (assert= "foobarbaz" (string-buffer->string buf))))
  (deftest
    "length tracks total bytes appended"
    (let
      ((buf (make-string-buffer)))
      (string-buffer-append! buf "abc")
      (string-buffer-append! buf "de")
      (assert= 5 (string-buffer-length buf))))
  (deftest
    "append returns nil"
    (let
      ((buf (make-string-buffer)))
      (assert= nil (string-buffer-append! buf "x"))))
  (deftest
    "appending empty string is harmless"
    (let
      ((buf (make-string-buffer)))
      (string-buffer-append! buf "start")
      (string-buffer-append! buf "")
      (string-buffer-append! buf "end")
      (assert= "startend" (string-buffer->string buf))
      (assert= 8 (string-buffer-length buf))))
  (deftest
    "buffer is still usable after string-buffer->string"
    (let
      ((buf (make-string-buffer)))
      (string-buffer-append! buf "hello")
      (string-buffer->string buf)
      (string-buffer-append! buf " world")
      (assert= "hello world" (string-buffer->string buf))))
  (deftest
    "two buffers are independent"
    (let
      ((b1 (make-string-buffer)) (b2 (make-string-buffer)))
      (string-buffer-append! b1 "one")
      (string-buffer-append! b2 "two")
      (string-buffer-append! b1 "ONE")
      (assert= "oneONE" (string-buffer->string b1))
      (assert= "two" (string-buffer->string b2))))
  (deftest
    "loop building — linear string concat"
    (let
      ((buf (make-string-buffer)))
      (let
        loop
        ((i 0))
        (when
          (< i 5)
          (string-buffer-append! buf (str i))
          (loop (+ i 1))))
      (assert= "01234" (string-buffer->string buf))
      (assert= 5 (string-buffer-length buf))))
  (deftest
    "building CSV row with separator"
    (let
      ((buf (make-string-buffer)) (items (list "a" "b" "c" "d")))
      (let
        loop
        ((remaining items) (is-first true))
        (when
          (not (empty? remaining))
          (when (not is-first) (string-buffer-append! buf ","))
          (string-buffer-append! buf (first remaining))
          (loop (rest remaining) false)))
      (assert= "a,b,c,d" (string-buffer->string buf))))
  (deftest
    "unicode characters accumulate correctly"
    (let
      ((buf (make-string-buffer)))
      (string-buffer-append! buf "こんにちは")
      (string-buffer-append! buf " ")
      (string-buffer-append! buf "世界")
      (assert= "こんにちは 世界" (string-buffer->string buf))))
  (deftest
    "repeated to-string calls are consistent"
    (let
      ((buf (make-string-buffer)))
      (string-buffer-append! buf "test")
      (assert= (string-buffer->string buf) (string-buffer->string buf))))
  (deftest
    "building with join pattern produces correct output"
    (let
      ((buf (make-string-buffer))
        (words (list "the" "quick" "brown" "fox")))
      (let
        loop
        ((remaining words) (sep ""))
        (when
          (not (empty? remaining))
          (string-buffer-append! buf sep)
          (string-buffer-append! buf (first remaining))
          (loop (rest remaining) " ")))
      (assert= "the quick brown fox" (string-buffer->string buf))))
  (deftest
    "make-buffer alias creates a buffer"
    (let ((b (make-buffer))) (assert (buffer? b))))
  (deftest
    "buffer-append! with string"
    (let ((b (make-buffer)))
      (buffer-append! b "hello")
      (buffer-append! b " ")
      (buffer-append! b "world")
      (assert= "hello world" (buffer->string b))))
  (deftest
    "buffer-append! coerces non-string values"
    (let ((b (make-buffer)))
      (buffer-append! b "n=")
      (buffer-append! b 42)
      (buffer-append! b ",")
      (buffer-append! b true)
      (buffer-append! b ",")
      (buffer-append! b nil)
      (assert= "n=42,true," (buffer->string b))))
  (deftest
    "buffer-length tracks total length"
    (let ((b (make-buffer)))
      (buffer-append! b "abc")
      (buffer-append! b "de")
      (assert= 5 (buffer-length b))))
  (deftest
    "buffer aliases interop with string-buffer"
    (let ((b (make-buffer)))
      (buffer-append! b "x")
      (string-buffer-append! b "y")
      (assert= "xy" (string-buffer->string b))
      (assert= "xy" (buffer->string b)))))
