;; ---------------------------------------------------------------------------
;; L1: Foreign
;; ---------------------------------------------------------------------------
(defcomp ()
  (~docs/page :title "Layer 1: Foreign (Host API Interop)"

    (p (~tw :tokens "text-stone-500 text-sm italic mb-8")
      "Clean boundary for calling host APIs — Canvas, WebGL, WebAudio, any browser API — "
      "from SX code. Function factories with automatic kebab-to-camelCase conversion.")

    (~docs/section :title "Live Demo" :id "demo"
      (p "Click the canvas to place colored rectangles. Uses " (code "host-call") " for canvas 2D context method calls and " (code "host-set!") " for property writes — the raw primitives that " (code "foreign-method") " and " (code "foreign-prop-setter") " will wrap.")
      (~reactive-runtime/demo-foreign)
      (~docs/code :src (highlight "(defisland ~demo-foreign ()\n  (let ((canvas-ref (dict \"current\" nil))\n        (color (signal \"#8b5cf6\"))\n        (rects (signal (list))))\n    ;; Draw effect — re-runs when rects changes\n    (effect (fn ()\n      (let ((el (get canvas-ref \"current\")))\n        (when el\n          (let ((ctx (host-call el \"getContext\" \"2d\")))\n            (host-call ctx \"clearRect\" 0 0 280 160)\n            (for-each (fn (r)\n              (host-set! ctx \"fillStyle\" (get r \"c\"))\n              (host-call ctx \"fillRect\" (get r \"x\") (get r \"y\") 20 20))\n              (deref rects)))))))\n    (canvas :ref canvas-ref :on-click (fn (e) ...)\n      :width \"280\" :height \"160\")))" "lisp"))
      (p "Every canvas operation is a raw " (code "host-call") " or " (code "host-set!") ". The foreign FFI layer wraps these into named SX functions: " (code "(fill-rect ctx 0 0 280 160)") " instead of " (code "(host-call ctx \"fillRect\" 0 0 280 160)") "."))

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

      (~docs/code :src (highlight
        ";; Function factories — each returns a reusable function\n(define fill-rect     (foreign-method \"fill-rect\"))\n(define set-fill-style! (foreign-prop-setter \"fill-style\"))\n(define get-width     (foreign-prop-getter \"width\"))\n\n;; Usage — clean SX calls, no string method names\n(let ((ctx (host-call canvas \"getContext\" \"2d\")))\n  (set-fill-style! ctx \"red\")\n  (fill-rect ctx 0 0 (get-width canvas) 100))"
        "lisp"))

      (p "Three factory functions, one helper:")
      (ul (~tw :tokens "list-disc pl-6 mb-4 space-y-1")
        (li (code "foreign-method") " — wraps " (code "host-call") " with kebab→camel conversion")
        (li (code "foreign-prop-getter") " — wraps " (code "host-get"))
        (li (code "foreign-prop-setter") " — wraps " (code "host-set!"))
        (li (code "kebab->camel") " — " (code "\"fill-rect\"") " → " (code "\"fillRect\""))))

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

      (~docs/code :src (highlight
        "(define kebab->camel (fn (s)\n  ;; \"fill-rect\" → \"fillRect\", \"font-size\" → \"fontSize\"\n  (let ((parts (split s \"-\"))\n        (first-part (first parts))\n        (rest-parts (rest parts)))\n    (str first-part\n      (join \"\" (map (fn (p)\n        (str (upper (slice p 0 1)) (slice p 1))) rest-parts))))))\n\n(define foreign-method (fn (method-name)\n  (let ((camel (kebab->camel method-name)))\n    (fn (obj &rest args)\n      (apply host-call (concat (list obj camel) args))))))\n\n(define foreign-prop-getter (fn (prop-name)\n  (let ((camel (kebab->camel prop-name)))\n    (fn (obj) (host-get obj camel)))))\n\n(define foreign-prop-setter (fn (prop-name)\n  (let ((camel (kebab->camel prop-name)))\n    (fn (obj val) (host-set! obj camel val)))))"
        "lisp"))

      (p "~100 lines. Uses existing host FFI primitives — no new platform interface needed."))))
