;; Reference API endpoints — live demos for hypermedia attribute docs
;;
;; These replace the Python endpoints in bp/pages/routes.py.
;; Each defhandler with :path registers as a public route automatically.

;; --- sx-get demo: server time ---

(defhandler ref-time
  :path "/sx/(geography.(hypermedia.(reference.(api.time))))"
  :method :get
  :returns "element"
  (&key)
  (let ((now (helper "now" "%H:%M:%S")))
    (<>
      (span (~tw :tokens "text-stone-800 text-sm") "Server time: " (strong now))
      (~docs/oob-code :target-id "ref-wire-sx-get"
        :text (str "(span :class \"text-stone-800 text-sm\" \"Server time: \" (strong \"" now "\"))")))))

;; --- sx-post demo: greet ---

(defhandler ref-greet
  :path "/sx/(geography.(hypermedia.(reference.(api.greet))))"
  :method :post
  :csrf false
  :returns "element"
  (&key)
  (let ((name (helper "request-form" "name" "stranger")))
    (<>
      (span (~tw :tokens "text-stone-800 text-sm") "Hello, " (strong name) "!")
      (~docs/oob-code :target-id "ref-wire-sx-post"
        :text (str "(span :class \"text-stone-800 text-sm\" \"Hello, \" (strong \"" name "\") \"!\")")))))

;; --- sx-put demo: status update ---

(defhandler ref-status
  :path "/sx/(geography.(hypermedia.(reference.(api.status))))"
  :method :put
  :csrf false
  :returns "element"
  (&key)
  (let ((status (helper "request-form" "status" "unknown")))
    (<>
      (span (~tw :tokens "text-stone-700 text-sm") "Status: " (strong status) " — updated via PUT")
      (~docs/oob-code :target-id "ref-wire-sx-put"
        :text (str "(span :class \"text-stone-700 text-sm\" \"Status: \" (strong \"" status "\") \" — updated via PUT\")")))))

;; --- sx-patch demo: theme ---

(defhandler ref-theme
  :path "/sx/(geography.(hypermedia.(reference.(api.theme))))"
  :method :patch
  :csrf false
  :returns "element"
  (&key)
  (let ((theme (helper "request-form" "theme" "unknown")))
    (<>
      theme
      (~docs/oob-code :target-id "ref-wire-sx-patch"
        :text (str "\"" theme "\"")))))

;; --- sx-delete demo ---

(defhandler ref-delete-item
  :path "/sx/(geography.(hypermedia.(reference.(api.(item.<sx:item_id>)))))"
  :method :delete
  :csrf false
  :returns "element"
  (&key)
  (<>
    (~docs/oob-code :target-id "ref-wire-sx-delete" :text "\"\"")))

;; --- sx-trigger demo: search ---

(defhandler ref-trigger-search
  :path "/sx/(geography.(hypermedia.(reference.(api.trigger-search))))"
  :method :get
  :returns "element"
  (&key)
  (let ((q (helper "request-arg" "q" "")))
    (let ((sx-text (if (= q "")
                     "(span :class \"text-stone-400 text-sm\" \"Start typing to trigger a search.\")"
                     (str "(span :class \"text-stone-800 text-sm\" \"Results for: \" (strong \"" q "\"))"))))
      (<>
        (if (= q "")
          (span (~tw :tokens "text-stone-400 text-sm") "Start typing to trigger a search.")
          (span (~tw :tokens "text-stone-800 text-sm") "Results for: " (strong q)))
        (~docs/oob-code :target-id "ref-wire-sx-trigger" :text sx-text)))))

;; --- sx-swap demo ---

(defhandler ref-swap-item
  :path "/sx/(geography.(hypermedia.(reference.(api.swap-item))))"
  :method :get
  :returns "element"
  (&key)
  (let ((now (helper "now" "%H:%M:%S")))
    (<>
      (div (~tw :tokens "text-sm text-violet-700") (str "New item (" now ")"))
      (~docs/oob-code :target-id "ref-wire-sx-swap"
        :text (str "(div :class \"text-sm text-violet-700\" \"New item (" now ")\")")))))

;; --- sx-swap-oob demo ---

(defhandler ref-oob
  :path "/sx/(geography.(hypermedia.(reference.(api.oob))))"
  :method :get
  :returns "element"
  (&key)
  (let ((now (helper "now" "%H:%M:%S")))
    (<>
      (span (~tw :tokens "text-emerald-700 text-sm") "Main updated at " now)
      (div :id "ref-oob-side" :sx-swap-oob "innerHTML"
        (span (~tw :tokens "text-violet-700 text-sm") "OOB updated at " now))
      (~docs/oob-code :target-id "ref-wire-sx-swap-oob"
        :text (str "(<> (span ... \"" now "\") (div :id \"ref-oob-side\" :sx-swap-oob \"innerHTML\" ...))")))))

;; --- sx-select demo ---

(defhandler ref-select-page
  :path "/sx/(geography.(hypermedia.(reference.(api.select-page))))"
  :method :get
  :returns "element"
  (&key)
  (let ((now (helper "now" "%H:%M:%S")))
    (<>
      (div :id "the-header" (h3 "Page header — not selected"))
      (div :id "the-content"
        (span (~tw :tokens "text-emerald-700 text-sm")
          "This fragment was selected from a larger response. Time: " now))
      (div :id "the-footer" (p "Page footer — not selected"))
      (~docs/oob-code :target-id "ref-wire-sx-select"
        :text (str "(<> (div :id \"the-header\" ...) (div :id \"the-content\" ... \"" now "\") (div :id \"the-footer\" ...))")))))

;; --- sx-sync demo: slow echo ---

(defhandler ref-slow-echo
  :path "/sx/(geography.(hypermedia.(reference.(api.slow-echo))))"
  :method :get
  :returns "element"
  (&key)
  (let ((q (helper "request-arg" "q" "")))
    (sleep 800)
    (<>
      (span (~tw :tokens "text-stone-800 text-sm") "Echo: " (strong q))
      (~docs/oob-code :target-id "ref-wire-sx-sync"
        :text (str "(span :class \"text-stone-800 text-sm\" \"Echo: \" (strong \"" q "\"))")))))

;; --- sx-prompt demo ---

(defhandler ref-prompt-echo
  :path "/sx/(geography.(hypermedia.(reference.(api.prompt-echo))))"
  :method :get
  :returns "element"
  (&key)
  (let ((name (helper "request-header" "SX-Prompt" "anonymous")))
    (<>
      (span (~tw :tokens "text-stone-800 text-sm") "Hello, " (strong name) "!")
      (~docs/oob-code :target-id "ref-wire-sx-prompt"
        :text (str "(span :class \"text-stone-800 text-sm\" \"Hello, \" (strong \"" name "\") \"!\")")))))

;; --- Error demo ---

(defhandler ref-error-500
  :path "/sx/(geography.(hypermedia.(reference.(api.error-500))))"
  :method :get
  :returns "nil"
  (&key)
  (abort 500 "Server error"))


;; ==========================================================================
;; Remaining reference endpoints — migrated from Python
;; ==========================================================================

;; --- sx-encoding demo: file upload name ---

(defhandler ref-upload-name
  :path "/sx/(geography.(hypermedia.(reference.(api.upload-name))))"
  :method :post
  :csrf false
  :returns "element"
  (&key)
  (let ((name (helper "request-file-name" "file")))
    (let ((display (if (nil? name) "(no file)" name)))
      (let ((sx-text (str "(span :class \"text-stone-800 text-sm\" \"Received: \" (strong \"" display "\"))")))
        (<>
          (span (~tw :tokens "text-stone-800 text-sm") "Received: " (strong display))
          (~docs/oob-code :target-id "ref-wire-sx-encoding" :text sx-text))))))

;; --- sx-headers demo: echo custom headers ---

(defhandler ref-echo-headers
  :path "/sx/(geography.(hypermedia.(reference.(api.echo-headers))))"
  :method :get
  :returns "element"
  (&key)
  (let ((all-headers (into (list) (helper "request-headers-all"))))
    (let ((custom (filter
                    (fn (pair) (starts-with? (first pair) "x-"))
                    all-headers)))
      (let ((sx-text
              (if (empty? custom)
                "(span :class \"text-stone-400 text-sm\" \"No custom headers received.\")"
                (str "(ul :class \"text-sm text-stone-700 space-y-1\" "
                     (join " " (map (fn (pair) (str "(li (strong \"" (first pair) "\") \": \" \"" (nth pair 1) "\")")) custom))
                     ")"))))
        (<>
          (if (empty? custom)
            (span (~tw :tokens "text-stone-400 text-sm") "No custom headers received.")
            (ul (~tw :tokens "text-sm text-stone-700 space-y-1")
              (map (fn (pair) (li (strong (first pair)) ": " (nth pair 1))) custom)))
          (~docs/oob-code :target-id "ref-wire-sx-headers" :text sx-text))))))

;; --- sx-include demo: echo GET query params ---

(defhandler ref-echo-vals-get
  :path "/sx/(geography.(hypermedia.(reference.(api.echo-vals))))"
  :method :get
  :returns "element"
  (&key)
  (let ((vals (into (list) (helper "request-args-all"))))
    (let ((sx-text
            (if (empty? vals)
              "(span :class \"text-stone-400 text-sm\" \"No values received.\")"
              (str "(ul :class \"text-sm text-stone-700 space-y-1\" "
                   (join " " (map (fn (pair) (str "(li (strong \"" (first pair) "\") \": \" \"" (nth pair 1) "\")")) vals))
                   ")"))))
      (<>
        (if (empty? vals)
          (span (~tw :tokens "text-stone-400 text-sm") "No values received.")
          (ul (~tw :tokens "text-sm text-stone-700 space-y-1")
            (map (fn (pair) (li (strong (first pair)) ": " (nth pair 1))) vals)))
        (~docs/oob-code :target-id "ref-wire-sx-include" :text sx-text)))))

;; --- sx-vals demo: echo POST form values ---

(defhandler ref-echo-vals-post
  :path "/sx/(geography.(hypermedia.(reference.(api.echo-vals))))"
  :method :post
  :csrf false
  :returns "element"
  (&key)
  (let ((vals (into (list) (helper "request-form-all"))))
    (let ((sx-text
            (if (empty? vals)
              "(span :class \"text-stone-400 text-sm\" \"No values received.\")"
              (str "(ul :class \"text-sm text-stone-700 space-y-1\" "
                   (join " " (map (fn (pair) (str "(li (strong \"" (first pair) "\") \": \" \"" (nth pair 1) "\")")) vals))
                   ")"))))
      (<>
        (if (empty? vals)
          (span (~tw :tokens "text-stone-400 text-sm") "No values received.")
          (ul (~tw :tokens "text-sm text-stone-700 space-y-1")
            (map (fn (pair) (li (strong (first pair)) ": " (nth pair 1))) vals)))
        (~docs/oob-code :target-id "ref-wire-sx-vals" :text sx-text)))))

;; --- sx-retry demo: flaky endpoint (fails 2/3 times) ---

(defhandler ref-flaky
  :path "/sx/(geography.(hypermedia.(reference.(api.flaky))))"
  :method :get
  :returns "element"
  (&key)
  (let ((prev (helper "state-get" "ref-flaky-n" 0)))
    (let ((n (+ prev 1)))
    (helper "state-set!" "ref-flaky-n" n)
    (if (not (= (mod n 3) 0))
      (do
        (set-response-status 503)
        "")
      (let ((sx-text (str "(span :class \"text-emerald-700 text-sm\" \"Success on attempt \" \"" n "\" \"!\")")))
        (<>
          (span (~tw :tokens "text-emerald-700 text-sm") "Success on attempt " (str n) "!")
          (~docs/oob-code :target-id "ref-wire-sx-retry" :text sx-text)))))))

;; --- sx-trigger-event demo: response header triggers ---

(defhandler ref-trigger-event
  :path "/sx/(geography.(hypermedia.(reference.(api.trigger-event))))"
  :method :get
  :returns "element"
  (&key)
  (let ((now (helper "now" "%H:%M:%S")))
    (set-response-header "SX-Trigger" "showNotice")
    (<>
      (span (~tw :tokens "text-stone-800 text-sm") "Loaded at " (strong now) " — check the border!"))))

;; --- sx-retarget demo: response header retargets ---

(defhandler ref-retarget
  :path "/sx/(geography.(hypermedia.(reference.(api.retarget))))"
  :method :get
  :returns "element"
  (&key)
  (let ((now (helper "now" "%H:%M:%S")))
    (set-response-header "SX-Retarget" "#ref-hdr-retarget-alt")
    (<>
      (span (~tw :tokens "text-violet-700 text-sm") "Retargeted at " (strong now)))))
