(defsuite
  "page-data-cache"
  (deftest
    "cache-key bare page name"
    (assert-equal "my-page" (page-data-cache-key "my-page" nil)))
  (deftest
    "cache-key with params"
    (let
      ((key (page-data-cache-key "my-page" {:id "42"})))
      (assert-equal "my-page:id=42" key)))
  (deftest
    "cache-set then get"
    (let
      ((key "test-cache-1"))
      (page-data-cache-set key {:items (list 1 2 3)})
      (let
        ((result (page-data-cache-get key)))
        (assert-equal (list 1 2 3) (get result "items")))))
  (deftest
    "cache miss returns nil"
    (assert-nil (page-data-cache-get "nonexistent-key"))))

(defsuite
  "optimistic-cache-update"
  (deftest
    "applies mutator to cached data"
    (let
      ((key "opt-test-1"))
      (page-data-cache-set key {:count 10})
      (let
        ((predicted (optimistic-cache-update key (fn (data) (merge data {:count 11})))))
        (assert-equal 11 (get predicted "count")))))
  (deftest
    "updates cache with prediction"
    (let
      ((key "opt-test-2"))
      (page-data-cache-set key {:count 5})
      (optimistic-cache-update key (fn (data) (merge data {:count 6})))
      (let
        ((cached (page-data-cache-get key)))
        (assert-equal 6 (get cached "count")))))
  (deftest
    "returns nil when no cached data"
    (let
      ((result (optimistic-cache-update "no-such-key" (fn (data) (merge data {:x 1})))))
      (assert-nil result))))

(defsuite
  "optimistic-cache-revert"
  (deftest
    "reverts to original data"
    (let
      ((key "revert-test-1"))
      (page-data-cache-set key {:count 10})
      (optimistic-cache-update key (fn (data) (merge data {:count 99})))
      (assert-equal 99 (get (page-data-cache-get key) "count"))
      (let
        ((restored (optimistic-cache-revert key)))
        (assert-equal 10 (get restored "count"))
        (assert-equal 10 (get (page-data-cache-get key) "count")))))
  (deftest
    "returns nil when no snapshot"
    (assert-nil (optimistic-cache-revert "never-mutated"))))

(defsuite
  "optimistic-cache-confirm"
  (deftest
    "confirm clears snapshot"
    (let
      ((key "confirm-test-1"))
      (page-data-cache-set key {:val "a"})
      (optimistic-cache-update key (fn (data) (merge data {:val "b"})))
      (optimistic-cache-confirm key)
      (assert-nil (optimistic-cache-revert key))
      (assert-equal "b" (get (page-data-cache-get key) "val")))))

(defsuite
  "offline-connectivity"
  (deftest "initially online" (assert-true (offline-is-online?)))
  (deftest
    "set offline"
    (offline-set-online! false)
    (assert-false (offline-is-online?)))
  (deftest
    "set back online"
    (offline-set-online! true)
    (assert-true (offline-is-online?))))

(defsuite
  "offline-queue-mutation"
  (deftest
    "queues an entry"
    (let
      ((key (page-data-cache-key "notes" nil)))
      (page-data-cache-set key {:items (list "a" "b")})
      (let
        ((entry (offline-queue-mutation "add-note" {:text "c"} "notes" nil (fn (data) (merge data {:items (list "a" "b" "c")})))))
        (assert-equal "add-note" (get entry "action"))
        (assert-equal "pending" (get entry "status")))))
  (deftest
    "pending count increases"
    (assert-true (> (offline-pending-count) 0))))

(define
  execute-action
  (fn (action-name payload success-fn error-fn) (success-fn nil)))

(defsuite
  "offline-aware-mutation"
  (deftest
    "when online calls submit-mutation path"
    (offline-set-online! true)
    (let
      ((key (page-data-cache-key "test-page" nil)))
      (page-data-cache-set key {:v 1})
      (let
        ((status nil))
        (offline-aware-mutation
          "test-page"
          nil
          "do-thing"
          {:x 1}
          (fn (data) (merge data {:v 2}))
          (fn (s) (set! status s)))
        (assert-equal "confirmed" status))))
  (deftest
    "when offline queues mutation"
    (offline-set-online! false)
    (let
      ((key (page-data-cache-key "test-page-2" nil)))
      (page-data-cache-set key {:v 1})
      (let
        ((status nil))
        (offline-aware-mutation
          "test-page-2"
          nil
          "do-thing"
          {:x 1}
          (fn (data) (merge data {:v 2}))
          (fn (s) (set! status s)))
        (assert-equal "queued" status)))
    (offline-set-online! true)))
