; Phase 4 — blob backend: store the ref, never the bytes. Bytes live in a
; separate content-addressed store (mock here).

(persist-test
  "blob-ref carries cid"
  (persist/blob-cid (persist/blob-ref "c1" 10 "image/png"))
  "c1")
(persist-test
  "blob-ref carries size"
  (persist/blob-size (persist/blob-ref "c1" 10 "image/png"))
  10)
(persist-test
  "blob-ref carries mime"
  (persist/blob-mime (persist/blob-ref "c1" 10 "image/png"))
  "image/png")
(persist-test
  "blob-ref? true for a ref"
  (persist/blob-ref? (persist/blob-ref "c1" 1 "x"))
  true)
(persist-test
  "blob-ref? false for a plain dict"
  (persist/blob-ref? {:n 1})
  false)

(persist-test
  "store returns a ref, not the bytes"
  (let
    ((blob (persist/mock-blob (persist/mem-backend))))
    (persist/blob-ref? (persist/blob-store blob "PNGDATA" "image/png")))
  true)
(persist-test
  "store records the byte length as size"
  (let
    ((blob (persist/mock-blob (persist/mem-backend))))
    (persist/blob-size (persist/blob-store blob "12345" "text/plain")))
  5)
(persist-test
  "fetch round-trips the bytes via the ref"
  (let
    ((blob (persist/mock-blob (persist/mem-backend))))
    (let
      ((ref (persist/blob-store blob "PAYLOAD" "text/plain")))
      (persist/blob-fetch blob ref)))
  "PAYLOAD")
(persist-test
  "exists? true after store"
  (let
    ((blob (persist/mock-blob (persist/mem-backend))))
    (let
      ((ref (persist/blob-store blob "X" "text/plain")))
      (persist/blob-exists? blob ref)))
  true)
(persist-test
  "content addressing: same bytes dedupe to same cid"
  (let
    ((blob (persist/mock-blob (persist/mem-backend))))
    (equal?
      (persist/blob-cid (persist/blob-store blob "SAME" "text/plain"))
      (persist/blob-cid (persist/blob-store blob "SAME" "text/plain"))))
  true)
(persist-test
  "different bytes get different cids"
  (let
    ((blob (persist/mock-blob (persist/mem-backend))))
    (equal?
      (persist/blob-cid (persist/blob-store blob "A" "text/plain"))
      (persist/blob-cid (persist/blob-store blob "B" "text/plain"))))
  false)

; ---------- the invariant: persist holds the ref, never the bytes ----------
(persist-test
  "a blob ref stored in kv is a ref"
  (let
    ((db (persist/mock-durable (persist/mem-backend)))
      (blob (persist/mock-blob (persist/mem-backend))))
    (begin
      (persist/kv-put
        db
        "avatar"
        (persist/blob-store blob "BIGIMAGE" "image/png"))
      (persist/blob-ref? (persist/kv-get db "avatar"))))
  true)
(persist-test
  "the kv value does not contain the bytes"
  (let
    ((db (persist/mock-durable (persist/mem-backend)))
      (blob (persist/mock-blob (persist/mem-backend))))
    (begin
      (persist/kv-put
        db
        "avatar"
        (persist/blob-store blob "BIGIMAGE" "image/png"))
      (has-key? (persist/kv-get db "avatar") :bytes)))
  false)
(persist-test
  "a blob ref stored in the log is a ref, bytes fetched separately"
  (let
    ((db (persist/mock-durable (persist/mem-backend)))
      (store (persist/mem-backend)))
    (let
      ((blob (persist/mock-blob store)))
      (begin
        (persist/append
          db
          "uploads"
          "added"
          0
          (persist/blob-store blob "FILEBYTES" "application/pdf"))
        (let
          ((ref (persist/event-data (first (persist/read db "uploads")))))
          (list (persist/blob-ref? ref) (persist/blob-fetch blob ref))))))
  (list true "FILEBYTES"))
