;; Protocol documentation pages — fully self-contained

(defcomp ~protocol-wire-format-content ()
  (~doc-page :title "Wire Format"
    (~doc-section :title "The text/sx content type" :id "content-type"
      (p :class "text-stone-600"
        "sx responses use content type text/sx. The body is s-expression source code. The client parses and evaluates it, then renders the result into the DOM.")
      (~doc-code :code (highlight "HTTP/1.1 200 OK\nContent-Type: text/sx\nSX-Css-Hash: a1b2c3d4\n\n(div :class \"p-4\"\n  (~card :title \"Hello\"))" "bash")))
    (~doc-section :title "Request lifecycle" :id "lifecycle"
      (p :class "text-stone-600"
        "1. User interacts with an element that has sx-get/sx-post/etc.")
      (p :class "text-stone-600"
        "2. sx.js fires sx:beforeRequest, then sends the HTTP request with SX-Request: true header.")
      (p :class "text-stone-600"
        "3. Server builds s-expression tree, scans CSS classes, prepends missing component definitions.")
      (p :class "text-stone-600"
        "4. Client receives text/sx response, parses it, evaluates it, renders to DOM.")
      (p :class "text-stone-600"
        "5. sx.js fires sx:afterSwap and sx:afterSettle.")
      (p :class "text-stone-600"
        "6. Any sx-swap-oob elements are swapped into their targets elsewhere in the DOM."))
    (~doc-section :title "Component definitions" :id "components"
      (p :class "text-stone-600"
        "On full page loads, component definitions are in <script type=\"text/sx\" data-components>. On subsequent sx requests, missing definitions are prepended to the response body. The client caches definitions in localStorage keyed by a content hash."))))

(defcomp ~protocol-fragments-content ()
  (~doc-page :title "Cross-Service Fragments"
    (~doc-section :title "Fragment protocol" :id "protocol"
      (p :class "text-stone-600"
        "Rose Ash runs as independent microservices. Each service can expose HTML or sx fragments that other services compose into their pages. Fragment endpoints return text/sx or text/html.")
      (p :class "text-stone-600"
        "The frag resolver is an I/O primitive in the render tree:")
      (~doc-code :code (highlight "(frag \"blog\" \"link-card\" :slug \"hello\")" "lisp")))
    (~doc-section :title "SxExpr wrapping" :id "wrapping"
      (p :class "text-stone-600"
        "When a fragment returns text/sx, the response is wrapped in an SxExpr and embedded directly in the render tree. When it returns text/html, it's wrapped in a ~rich-text component that inserts the HTML via raw!. This allows transparent composition across service boundaries."))
    (~doc-section :title "fetch_fragments()" :id "fetch"
      (p :class "text-stone-600"
        "The Python helper fetch_fragments() fetches multiple fragments in parallel via asyncio.gather(). Fragments are cached in Redis with short TTLs. Each fragment request is HMAC-signed for authentication."))))

(defcomp ~protocol-resolver-io-content ()
  (~doc-page :title "Resolver I/O"
    (~doc-section :title "Async I/O primitives" :id "primitives"
      (p :class "text-stone-600"
        "The sx resolver identifies I/O nodes in the render tree, groups them, executes them in parallel via asyncio.gather(), and substitutes results back in.")
      (p :class "text-stone-600"
        "I/O primitives:")
      (ul :class "space-y-2 text-stone-600"
        (li (span :class "font-mono text-violet-700" "frag") " — fetch a cross-service fragment")
        (li (span :class "font-mono text-violet-700" "query") " — read data from another service")
        (li (span :class "font-mono text-violet-700" "action") " — execute a write on another service")
        (li (span :class "font-mono text-violet-700" "current-user") " — resolve the current authenticated user")))
    (~doc-section :title "Execution model" :id "execution"
      (p :class "text-stone-600"
        "The render tree is walked to find I/O nodes. All nodes at the same depth are gathered and executed in parallel. Results replace the I/O nodes in the tree. The walk continues until no more I/O nodes are found. This typically completes in 1-2 passes."))))

(defcomp ~protocol-internal-services-content ()
  (~doc-page :title "Internal Services"
    (~doc-note
      (p "Honest note: the internal service protocol is JSON, not sx. Sx is the composition layer on top. The protocols below are the plumbing underneath."))
    (~doc-section :title "HMAC-signed HTTP" :id "hmac"
      (p :class "text-stone-600"
        "Services communicate via HMAC-signed HTTP requests with short timeouts:")
      (ul :class "space-y-2 text-stone-600 font-mono text-sm"
        (li "GET /internal/data/{query} — read data (3s timeout)")
        (li "POST /internal/actions/{action} — execute write (5s timeout)")
        (li "POST /internal/inbox — ActivityPub-shaped event delivery")))
    (~doc-section :title "fetch_data / call_action" :id "fetch"
      (p :class "text-stone-600"
        "Python helpers fetch_data() and call_action() handle HMAC signing, serialization, and error handling. They resolve service URLs from environment variables (INTERNAL_URL_BLOG, etc) and fall back to public URLs in development."))))

(defcomp ~protocol-activitypub-content ()
  (~doc-page :title "ActivityPub"
    (~doc-note
      (p "Honest note: ActivityPub wire format is JSON-LD, not sx. This documents how AP integrates with the sx rendering layer."))
    (~doc-section :title "AP activities" :id "activities"
      (p :class "text-stone-600"
        "Rose Ash services communicate cross-domain writes via ActivityPub-shaped activities. Each service has a virtual actor. Activities are JSON-LD objects sent to /internal/inbox endpoints. RSA signatures authenticate the sender."))
    (~doc-section :title "Event bus" :id "bus"
      (p :class "text-stone-600"
        "The event bus dispatches activities to registered handlers. Handlers are async functions that process the activity and may trigger side effects. The bus runs as a background processor in each service."))))

(defcomp ~protocol-future-content ()
  (~doc-page :title "Future Possibilities"
    (~doc-note
      (p "This page is speculative. Nothing here is implemented. It documents ideas that may or may not happen."))
    (~doc-section :title "Custom protocol schemes" :id "schemes"
      (p :class "text-stone-600"
        "sx:// and sxs:// as custom URI schemes for content addressing or deep linking. An sx:// URI could resolve to an sx expression from a federated registry. This is technically feasible but practically unnecessary for a single-site deployment."))
    (~doc-section :title "Sx as AP serialization" :id "ap-sx"
      (p :class "text-stone-600"
        "ActivityPub objects could be serialized as s-expressions instead of JSON-LD. S-expressions are more compact and easier to parse. The practical barrier: the entire AP ecosystem expects JSON-LD."))
    (~doc-section :title "Sx-native federation" :id "federation"
      (p :class "text-stone-600"
        "Federated services could exchange sx fragments directly — render a remote user's profile card by fetching its sx source from their server. This requires trust and standardization that doesn't exist yet."))
    (~doc-section :title "Realistic assessment" :id "realistic"
      (p :class "text-stone-600"
        "The most likely near-term improvement is sx:// deep linking for client-side component resolution. Everything else requires ecosystem adoption that one project can't drive alone."))))
