;; ---------------------------------------------------------------------------
;; L3: Commands — counter with undo/redo
;; ---------------------------------------------------------------------------
(defisland ()
  (let ((value (signal 0))
        (history (signal (list)))
        (future (signal (list)))
        (undo-class (signal "bg-stone-200 text-stone-400 cursor-not-allowed"))
        (redo-class (signal "bg-stone-200 text-stone-400 cursor-not-allowed")))
    (let ((do-cmd (fn (new-val)
            (let ((old-val (deref value))
                  (old-hist (deref history)))
              (do
                (reset! history (cons old-val old-hist))
                (reset! future (list))
                (reset! value new-val)))))
          (undo (fn ()
            (let ((h (deref history)))
              (when (> (len h) 0)
                (let ((prev (first h))
                      (old-val (deref value))
                      (f (deref future)))
                  (do
                    (reset! future (cons old-val f))
                    (reset! history (rest h))
                    (reset! value prev)))))))
          (redo (fn ()
            (let ((f (deref future)))
              (when (> (len f) 0)
                (let ((next-val (first f))
                      (old-val (deref value))
                      (h (deref history)))
                  (do
                    (reset! history (cons old-val h))
                    (reset! future (rest f))
                    (reset! value next-val)))))))
          (_e1 (effect (fn ()
            (reset! undo-class
              (if (> (len (deref history)) 0)
                "bg-stone-600 text-white hover:bg-stone-700"
                "bg-stone-200 text-stone-400 cursor-not-allowed")))))
          (_e2 (effect (fn ()
            (reset! redo-class
              (if (> (len (deref future)) 0)
                "bg-stone-600 text-white hover:bg-stone-700"
                "bg-stone-200 text-stone-400 cursor-not-allowed"))))))
      (div (~tw :tokens "rounded border border-violet-200 bg-violet-50 p-4 my-4")
        (div (~tw :tokens "flex items-center gap-3 mb-3")
          (span (~tw :tokens "text-3xl font-bold text-violet-900 font-mono w-20 text-center")
            (deref value))
          (div (~tw :tokens "flex gap-1")
            (button (~tw :tokens "px-3 py-1 rounded bg-violet-600 text-white text-sm font-medium hover:bg-violet-700")
              :on-click (fn (e) (do-cmd (+ (deref value) 1)))
              "+1")
            (button (~tw :tokens "px-3 py-1 rounded bg-violet-600 text-white text-sm font-medium hover:bg-violet-700")
              :on-click (fn (e) (do-cmd (+ (deref value) 5)))
              "+5")
            (button (~tw :tokens "px-3 py-1 rounded bg-violet-600 text-white text-sm font-medium hover:bg-violet-700")
              :on-click (fn (e) (do-cmd (* (deref value) 2)))
              "×2")
            (button (~tw :tokens "px-3 py-1 rounded bg-violet-600 text-white text-sm font-medium hover:bg-violet-700")
              :on-click (fn (e) (do-cmd 0))
              "0")))
        (div (~tw :tokens "flex items-center gap-3")
          (button :class (str "px-3 py-1 rounded text-sm font-medium " (deref undo-class))
            :on-click (fn (e) (undo))
            "Undo")
          (button :class (str "px-3 py-1 rounded text-sm font-medium " (deref redo-class))
            :on-click (fn (e) (redo))
            "Redo")
          (span (~tw :tokens "text-xs text-stone-400 font-mono")
            "history: " (deref (computed (fn () (len (deref history)))))))))))
