;; content-on-sx — deep tree editing.
;;
;; Mutate blocks anywhere in the nested tree (descending into CtSection children),
;; complementing the top-level doc ops and the deep-find read path. All return
;; new documents (immutable).
;;
;; Requires (loaded by harness): doc.sx, section.sx (section? / section-children /
;; section-with-children / section-append).

;; map f over every block in the tree, replacing the one whose id matches.
(define
  block-tree-update
  (fn
    (blocks id f)
    (map
      (fn
        (b)
        (if
          (= (blk-id b) id)
          (f b)
          (if
            (section? b)
            (section-with-children
              b
              (block-tree-update (section-children b) id f))
            b)))
      blocks)))

;; remove the block with id from anywhere in the tree.
(define
  block-tree-delete
  (fn
    (blocks id)
    (map
      (fn
        (b)
        (if
          (section? b)
          (section-with-children
            b
            (block-tree-delete (section-children b) id))
          b))
      (filter (fn (b) (if (= (blk-id b) id) false true)) blocks))))

;; append a block into the children of the section with section-id.
(define
  block-tree-insert-into
  (fn
    (blocks section-id block)
    (map
      (fn
        (b)
        (if
          (section? b)
          (if
            (= (blk-id b) section-id)
            (section-append b block)
            (section-with-children
              b
              (block-tree-insert-into (section-children b) section-id block)))
          b))
      blocks)))

;; ── document-level deep ops ──
(define
  doc-deep-update
  (fn
    (doc id field value)
    (doc-with-blocks
      doc
      (block-tree-update
        (doc-blocks doc)
        id
        (fn (b) (blk-set b field value))))))

(define
  doc-deep-replace
  (fn
    (doc id newblock)
    (doc-with-blocks
      doc
      (block-tree-update (doc-blocks doc) id (fn (b) newblock)))))

(define
  doc-deep-delete
  (fn
    (doc id)
    (doc-with-blocks doc (block-tree-delete (doc-blocks doc) id))))

(define
  doc-deep-insert-into
  (fn
    (doc section-id block)
    (doc-with-blocks
      doc
      (block-tree-insert-into (doc-blocks doc) section-id block))))
