;; ---------------------------------------------------------------------------
;; L2: State Machines
;; ---------------------------------------------------------------------------
(defcomp ()
  (~docs/page :title "Layer 2: State Machines"

    (p (~tw :tokens "text-stone-500 text-sm italic mb-8")
      "Modal state management where machine state IS a signal. "
      "Composes naturally with computed and effects.")

    (~docs/section :title "Live Demo" :id "demo"
      (p "A traffic light built from a signal and a transitions dict. Auto-advance uses an effect with " (code "set-timeout") " — when state changes, the effect re-runs and schedules the next transition.")
      (~reactive-runtime/demo-machine)
      (~docs/code :src (highlight "(defisland ~demo-machine ()\n  (let ((state (signal \"red\"))\n        (transitions (dict \"red\" \"green\" \"green\" \"yellow\" \"yellow\" \"red\"))\n        (auto (signal false)))\n    ;; Auto-advance: effect depends on both state and auto\n    (effect (fn ()\n      (when (deref auto)\n        (let ((delay (if (= (deref state) \"yellow\") 1000 2500)))\n          (let ((id (set-timeout\n              (fn () (reset! state (get transitions (deref state))))\n              delay)))\n            (fn () (clear-timeout id)))))))\n    ;; Display: reactive class on each light\n    (div :class (str \"...\" (if (= (deref state) \"red\")\n      \"bg-red-500\" \"bg-red-900/30\")) ...)))" "lisp"))
      (p "The machine state is a signal — " (code "(deref state)") " in the effect body subscribes, so when the timeout fires and resets state, the effect re-runs with the new delay. The " (code "make-machine") " function wraps this pattern with transition tables, guards, and enter/exit hooks."))

    (~docs/section :title "API" :id "machine-api"

      (~docs/code :src (highlight
        "(define drawing-tool (make-machine\n  {:initial :idle\n   :states {:idle    {:on {:pointer-down (fn (ev)\n                           {:state :drawing\n                            :actions (list (fn () (start-shape! ev)))})}}\n            :drawing {:on {:pointer-move (fn (ev)\n                           {:state :drawing\n                            :actions (list (fn () (update-shape! ev)))})\n                          :pointer-up (fn (ev)\n                           {:state :idle\n                            :actions (list (fn () (finish-shape! ev)))})}}}}))\n\n;; Send events\n(machine-send! drawing-tool :pointer-down event)\n\n;; Read state (reactive — triggers re-render)\n(deref (machine-state drawing-tool))   ;; => :drawing\n(machine-matches? drawing-tool :idle)  ;; => false"
        "lisp"))

      (p (code "make-machine") " returns a dict with a state signal, transitions map, and send function. "
         "Handlers return " (code "{:state :new-state :actions [fn ...]}") " — "
         "actions are called after the state transition."))

    (~docs/section :title "Implementation Sketch" :id "machine-impl"

      (~docs/code :src (highlight
        "(define make-machine (fn (config)\n  (let ((current (signal (get config :initial)))\n        (states  (get config :states)))\n    (dict\n      \"__machine\" true\n      \"state\"    current\n      \"states\"   states))))\n\n(define machine-state (fn (m) (get m \"state\")))\n\n(define machine-matches? (fn (m s)\n  (= (deref (get m \"state\")) s)))\n\n(define machine-send! (fn (m event &rest data)\n  (let ((current-state (deref (get m \"state\")))\n        (state-config  (get (get m \"states\") current-state))\n        (handlers      (get state-config :on))\n        (handler       (get handlers event)))\n    (when handler\n      (let ((result (apply handler data)))\n        (when (get result :state)\n          (reset! (get m \"state\") (get result :state)))\n        (when (get result :actions)\n          (for-each (fn (action) (action))\n            (get result :actions))))))))"
        "lisp"))

      (p "~200 lines with guard conditions, context data, and enter/exit hooks."))))
