;; Phase 1 — public API facade. End-to-end through content/*.

(st-bootstrap-classes!)
(content/bootstrap!)

;; ── build a document via the facade ──
(define d0 (content/empty "post"))
(define
  h
  (content/block
    "heading"
    "h"
    (list (list "level" 1) (list "text" "Hi"))))
(define p (content/block "text" "p" (list (list "text" "World"))))
(define d1 (content/append (content/append d0 h) p))

(content/op? (content/insert h nil))
(content-test "count" (content/count d1) 2)
(content-test "ids" (content/ids d1) (list "h" "p"))
(content-test "types" (content/types d1) (list "heading" "text"))
(content-test "find" (blk-id (content/find d1 "p")) "p")
(content-test "has? yes" (content/has? d1 "h") true)
(content-test "has? no" (content/has? d1 "x") false)

;; ── content/op? distinguishes a single op from a list / a block ──
(content-test "op? on insert" (content/op? (content/insert h nil)) true)
(content-test
  "op? on update"
  (content/op? (content/update "p" "text" "z"))
  true)
(content-test "op? on list" (content/op? (list (content/delete "h"))) false)
(content-test "op? on block" (content/op? h) false)
(content-test "op? on doc" (content/op? d1) false)

;; ── edit with a single op ──
(define
  img
  (content/block
    "image"
    "img"
    (list (list "src" "/c.png") (list "alt" "cat"))))
(define d2 (content/edit d1 (content/insert img "h")))
(content-test "edit single op order" (content/ids d2) (list "h" "img" "p"))
(content-test "edit single immutable" (content/ids d1) (list "h" "p"))
(content-test
  "edit update"
  (str
    (blk-send
      (content/find
        (content/edit d1 (content/update "p" "text" "Edited"))
        "p")
      "text"))
  "Edited")
(content-test
  "edit delete"
  (content/ids (content/edit d1 (content/delete "h")))
  (list "p"))
(content-test
  "edit move"
  (content/ids (content/edit d1 (content/move "p" 0)))
  (list "p" "h"))

;; ── edit with a stream of ops ──
(define ops (list (content/insert img "h") (content/delete "p")))
(content-test
  "edit op stream"
  (content/ids (content/edit d1 ops))
  (list "h" "img"))
(content-test "edit op stream immutable" (content/ids d1) (list "h" "p"))

;; ── render via facade ──
(content-test
  "render html"
  (content/render d1 "html")
  "<h1>Hi</h1><p>World</p>")
(content-test
  "render sx"
  (content/render d1 "sx")
  "(article (h1 \"Hi\")(p \"World\"))")
(content-test
  "render html keyword"
  (content/render d1 :html)
  "<h1>Hi</h1><p>World</p>")
(content-test
  "render sx keyword"
  (content/render d1 :sx)
  "(article (h1 \"Hi\")(p \"World\"))")
(content-test "content/html" (content/html d1) "<h1>Hi</h1><p>World</p>")
(content-test "content/sx" (content/sx d1) "(article (h1 \"Hi\")(p \"World\"))")

;; ── render reflects each version ──
(content-test
  "render edited version"
  (content/render (content/edit d1 (content/update "h" "text" "Hey")) "html")
  "<h1>Hey</h1><p>World</p>")
(content-test
  "render original unchanged"
  (content/render d1 "html")
  "<h1>Hi</h1><p>World</p>")

;; ── facade find/has? are TREE-WIDE (reach into sections); find-top/has-top?
;; keep the top-level-only lookup. This makes the read-by-id surface consistent
;; with content/edit, whose update/delete are already tree-wide. ──
(content-bootstrap-section!)
(define
  nd
  (content/append
    (content/empty "nested")
    (mk-section
      "sec"
      (list (content/block "text" "inner" (list (list "text" "deep")))))))
(content-test
  "find nested (deep)"
  (blk-id (content/find nd "inner"))
  "inner")
(content-test "has? nested (deep)" (content/has? nd "inner") true)
(content-test "find-top misses nested" (content/find-top nd "inner") nil)
(content-test "has-top? misses nested" (content/has-top? nd "inner") false)
(content-test
  "find-top sees top-level"
  (blk-id (content/find-top nd "sec"))
  "sec")
;; a nested block updated by id via content/edit is now readable by id via
;; content/find (was impossible when find was top-level-only).
(content-test
  "edit-then-find nested round-trip"
  (str
    (blk-send
      (content/find
        (content/edit nd (content/update "inner" "text" "edited"))
        "inner")
      "text"))
  "edited")
