;; ==========================================================================
;; Reactive API endpoints — live demos for marsh/reactive-islands pages
;;
;; Migrated from bp/pages/routes.py (Python f-string handlers).
;; ==========================================================================


;; --------------------------------------------------------------------------
;; Data constants
;; --------------------------------------------------------------------------

(define flash-sale-prices
  (list 14.99 9.99 24.99 12.49 7.99 29.99 4.99 16.50))

(define settle-items
  (list "Widget" "Gadget" "Sprocket" "Gizmo" "Doohickey"))

(define search-product-items
  (list "Artisan Widget" "Premium Gadget" "Handcrafted Sprocket"
        "Bespoke Gizmo" "Organic Doohickey"))

(define search-event-items
  (list "Summer Workshop" "Craft Fair" "Open Studio"
        "Artist Talk" "Gallery Opening"))

(define search-post-items
  (list "On Craft and Code" "The SX Manifesto" "Islands and Lakes"
        "Reactive Marshes" "Self-Hosting Spec"))

(define catalog-items
  (list
    (dict "name" "Artisan Widget"   "price" "19.99" "desc" "Hand-crafted with care")
    (dict "name" "Premium Gadget"   "price" "34.50" "desc" "Top-of-the-line quality")
    (dict "name" "Vintage Sprocket" "price" "12.99" "desc" "Classic design")
    (dict "name" "Custom Gizmo"     "price" "27.00" "desc" "Made to order")))


;; --------------------------------------------------------------------------
;; Helper: search results panel
;; --------------------------------------------------------------------------

(defcomp ~reactive-api/search-results (&key label color items query)
  (let ((matches (if (= query "")
                   items
                   (filter (fn (item) (string-contains? (lower item) (lower query)))
                           items))))
    (let ((shown (slice matches 0 3)))
      (div (~tw :tokens "space-y-1")
        (p :class (str "text-xs font-semibold uppercase " color) label)
        (ul (~tw :tokens "list-disc pl-4")
          (map (fn (m) (li (~tw :tokens "text-sm text-stone-600") m)) shown))
        (p (~tw :tokens "text-xs text-stone-400")
          (str (length matches) " result(s)"))))))


;; --------------------------------------------------------------------------
;; Flash Sale
;; --------------------------------------------------------------------------

(defhandler reactive-flash-sale
  :path "/sx/(geography.(reactive.(api.flash-sale)))"
  :method :get
  :returns "element"
  (&key)
  (let ((idx (random-int 0 (- (length flash-sale-prices) 1)))
        (now (helper "now" "%H:%M:%S")))
    (let ((price (nth flash-sale-prices idx)))
      (<>
        (div (~tw :tokens "space-y-2")
          (p (~tw :tokens "text-sm text-emerald-600 font-medium")
            (str "⚡ Flash sale! Price: $" price))
          (p (~tw :tokens "text-xs text-stone-400") (str "at " now)))
        (script :type "text/sx" :data-init ""
          (str "(reset! (use-store \"demo-price\") " price ")"))))))


;; --------------------------------------------------------------------------
;; Settle Data
;; --------------------------------------------------------------------------

(defhandler reactive-settle-data
  :path "/sx/(geography.(reactive.(api.settle-data)))"
  :method :get
  :returns "element"
  (&key)
  (let ((idx (random-int 0 (- (length settle-items) 1)))
        (now (helper "now" "%H:%M:%S")))
    (let ((item (nth settle-items idx)))
      (div (~tw :tokens "space-y-1")
        (p (~tw :tokens "text-sm font-medium text-stone-700") (str "Fetched: " item))
        (p (~tw :tokens "text-xs text-stone-400") (str "at " now))))))


;; --------------------------------------------------------------------------
;; Search Products
;; --------------------------------------------------------------------------

(defhandler reactive-search-products
  :path "/sx/(geography.(reactive.(api.search-products)))"
  :method :get
  :returns "element"
  (&key)
  (let ((q (helper "request-arg" "q" "")))
    (~reactive-api/search-results
      :label "Products" :color "text-violet-600"
      :items search-product-items :query q)))


;; --------------------------------------------------------------------------
;; Search Events
;; --------------------------------------------------------------------------

(defhandler reactive-search-events
  :path "/sx/(geography.(reactive.(api.search-events)))"
  :method :get
  :returns "element"
  (&key)
  (let ((q (helper "request-arg" "q" "")))
    (~reactive-api/search-results
      :label "Events" :color "text-emerald-600"
      :items search-event-items :query q)))


;; --------------------------------------------------------------------------
;; Search Posts
;; --------------------------------------------------------------------------

(defhandler reactive-search-posts
  :path "/sx/(geography.(reactive.(api.search-posts)))"
  :method :get
  :returns "element"
  (&key)
  (let ((q (helper "request-arg" "q" "")))
    (~reactive-api/search-results
      :label "Posts" :color "text-amber-600"
      :items search-post-items :query q)))


;; --------------------------------------------------------------------------
;; Catalog
;; --------------------------------------------------------------------------

(defhandler reactive-catalog
  :path "/sx/(geography.(reactive.(api.catalog)))"
  :method :get
  :returns "element"
  (&key)
  (let ((now (helper "now" "%H:%M:%S"))
        (idx (random-int 0 3)))
    ;; Rotate items by a random offset to simulate shuffle
    (let ((rotated (append (slice catalog-items idx (length catalog-items))
                           (slice catalog-items 0 idx))))
      (let ((items-sx
              (str "(list "
                (reduce (fn (acc item)
                  (str acc
                    "(dict \"name\" \"" (get item "name")
                    "\" \"price\" \"" (get item "price")
                    "\" \"desc\" \"" (get item "desc") "\") "))
                  "" rotated)
                ")")))
        (<>
          (p (~tw :tokens "text-sm text-emerald-600 font-medium")
            (str "Catalog loaded: " (length rotated) " items (shuffled at " now ")"))
          (script :type "text/sx" :data-init ""
            (str "(reset! (use-store \"catalog-items\") " items-sx ")")))))))
