; Phase 3 — compaction: drop the snapshotted prefix; replay determinism holds.

(define comp-count (fn (acc e) (+ acc 1)))

(persist-test
  "uncompacted counts events since snapshot"
  (let
    ((b (persist/open)))
    (begin
      (persist/append b "s" "x" 0 {})
      (persist/append b "s" "x" 0 {})
      (persist/uncompacted b "s" "snap" 0)))
  2)
(persist-test
  "should-compact? false below threshold"
  (let
    ((b (persist/open)))
    (begin
      (persist/append b "s" "x" 0 {})
      (persist/should-compact? b "s" "snap" 3 0)))
  false)
(persist-test
  "should-compact? true at threshold"
  (let
    ((b (persist/open)))
    (begin
      (persist/append b "s" "x" 0 {})
      (persist/append b "s" "x" 0 {})
      (persist/append b "s" "x" 0 {})
      (persist/should-compact? b "s" "snap" 3 0)))
  true)
(persist-test
  "compact truncates the snapshotted prefix"
  (let
    ((b (persist/open)))
    (begin
      (persist/append b "s" "x" 0 {})
      (persist/append b "s" "x" 0 {})
      (persist/append b "s" "x" 0 {})
      (persist/compact b "s" "snap" comp-count 0)
      (persist/count b "s")))
  0)
(persist-test
  "compact preserves logical last-seq"
  (let
    ((b (persist/open)))
    (begin
      (persist/append b "s" "x" 0 {})
      (persist/append b "s" "x" 0 {})
      (persist/compact b "s" "snap" comp-count 0)
      (persist/last-seq b "s")))
  2)
(persist-test
  "append after compaction continues the seq"
  (let
    ((b (persist/open)))
    (begin
      (persist/append b "s" "x" 0 {})
      (persist/append b "s" "x" 0 {})
      (persist/compact b "s" "snap" comp-count 0)
      (persist/event-seq (persist/append b "s" "x" 0 {}))))
  3)
(persist-test
  "replay after compaction == full count before compaction"
  (let
    ((b (persist/open)))
    (begin
      (persist/append b "s" "x" 0 {})
      (persist/append b "s" "x" 0 {})
      (persist/append b "s" "x" 0 {})
      (persist/compact b "s" "snap" comp-count 0)
      (persist/append b "s" "x" 0 {})
      (persist/append b "s" "x" 0 {})
      (persist/project-value
        (persist/replay b "s" "snap" comp-count 0))))
  5)
(persist-test
  "determinism: post-compaction replay value equals uncompacted full replay"
  (let
    ((b (persist/open)) (c (persist/open)))
    (begin
      (persist/append b "s" "x" 0 {})
      (persist/append b "s" "x" 0 {})
      (persist/append b "s" "x" 0 {})
      (persist/append c "s" "x" 0 {})
      (persist/append c "s" "x" 0 {})
      (persist/append c "s" "x" 0 {})
      (persist/compact b "s" "snap" comp-count 0)
      (persist/append b "s" "x" 0 {})
      (persist/append c "s" "x" 0 {})
      (equal?
        (persist/project-value
          (persist/replay b "s" "snap" comp-count 0))
        (persist/project-fold c "s" comp-count 0))))
  true)
(persist-test
  "maybe-compact below threshold does not truncate"
  (let
    ((b (persist/open)))
    (begin
      (persist/append b "s" "x" 0 {})
      (persist/maybe-compact b "s" "snap" comp-count 0 5)
      (persist/count b "s")))
  1)
(persist-test
  "maybe-compact at threshold truncates"
  (let
    ((b (persist/open)))
    (begin
      (persist/append b "s" "x" 0 {})
      (persist/append b "s" "x" 0 {})
      (persist/maybe-compact b "s" "snap" comp-count 0 2)
      (persist/count b "s")))
  0)
(persist-test
  "compact is idempotent on an empty tail"
  (let
    ((b (persist/open)))
    (begin
      (persist/append b "s" "x" 0 {})
      (persist/compact b "s" "snap" comp-count 0)
      (persist/project-value
        (persist/compact b "s" "snap" comp-count 0))))
  1)
