;; Blog index components

(defcomp ~index/no-pages ()
  (div :class "col-span-full mt-8 text-center text-stone-500" "No pages found."))

(defcomp ~index/content-type-tabs (&key posts-href pages-href hx-select posts-cls pages-cls)
  (div :class "flex justify-center gap-1 px-3 pt-3"
    (a :href posts-href :sx-get posts-href :sx-target "#main-panel"
      :sx-select hx-select :sx-swap "outerHTML" :sx-push-url "true"
      :class (str "px-4 py-1.5 rounded-t text-sm font-medium transition-colors " posts-cls) "Posts")
    (a :href pages-href :sx-get pages-href :sx-target "#main-panel"
      :sx-select hx-select :sx-swap "outerHTML" :sx-push-url "true"
      :class (str "px-4 py-1.5 rounded-t text-sm font-medium transition-colors " pages-cls) "Pages")))

(defcomp ~index/main-panel-pages (&key tabs cards)
  (<> tabs
      (div :class "max-w-full px-3 py-3 space-y-3" cards)
      (div :class "pb-8")))

(defcomp ~index/main-panel-posts (&key tabs toggle grid-cls cards)
  (<> tabs
      toggle
      (div :class grid-cls cards)
      (div :class "pb-8")))

(defcomp ~index/aside (&key search action-buttons tag-groups-filter authors-filter)
  (<> search
      action-buttons
    (div :id "category-summary-desktop" :hxx-swap-oob "outerHTML"
      tag-groups-filter
      authors-filter)
    (div :id "filter-summary-desktop" :hxx-swap-oob "outerHTML")))

;; ---------------------------------------------------------------------------
;; Data-driven composition defcomps — replace Python sx_components functions
;; ---------------------------------------------------------------------------

;; Helper: CSS class for filter item based on selection state
(defcomp ~index/filter-cls (&key is-on)
  ;; Returns nothing — use inline (if is-on ...) instead
  nil)

;; Blog index main content — replaces _blog_main_panel_sx
(defcomp ~index/main-content (&key content-type view cards page total-pages
                                        current-local-href hx-select blog-url-base)
  (let* ((posts-href (str blog-url-base "/index"))
         (pages-href (str posts-href "?type=pages"))
         (posts-cls (if (not (= content-type "pages"))
           "bg-stone-700 text-white" "bg-stone-100 text-stone-600 hover:bg-stone-200"))
         (pages-cls (if (= content-type "pages")
           "bg-stone-700 text-white" "bg-stone-100 text-stone-600 hover:bg-stone-200")))
    (if (= content-type "pages")
      ;; Pages listing
      (~index/main-panel-pages
        :tabs (~index/content-type-tabs
          :posts-href posts-href :pages-href pages-href
          :hx-select hx-select :posts-cls posts-cls :pages-cls pages-cls)
        :cards (<>
          (map (lambda (card)
            (~cards/page-card
              :href (get card "href") :hx-select hx-select
              :title (get card "title")
              :has-calendar (get card "has_calendar")
              :has-market (get card "has_market")
              :pub-timestamp (get card "pub_timestamp")
              :feature-image (get card "feature_image")
              :excerpt (get card "excerpt")))
            (or cards (list)))
          (if (< page total-pages)
            (~shared:misc/sentinel-simple
              :id (str "sentinel-" page "-d")
              :next-url (str current-local-href
                (if (contains? current-local-href "?") "&" "?")
                "page=" (+ page 1)))
            (if (not (empty? (or cards (list))))
              (~shared:misc/end-of-results)
              (~index/no-pages)))))
      ;; Posts listing
      (let* ((grid-cls (if (= view "tile")
               "max-w-full px-3 py-3 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4"
               "max-w-full px-3 py-3 space-y-3"))
             (list-href current-local-href)
             (tile-href (str current-local-href
               (if (contains? current-local-href "?") "&" "?") "view=tile"))
             (list-cls (if (not (= view "tile"))
               "bg-stone-200 text-stone-800"
               "text-stone-400 hover:text-stone-600"))
             (tile-cls (if (= view "tile")
               "bg-stone-200 text-stone-800"
               "text-stone-400 hover:text-stone-600")))
        (~index/main-panel-posts
          :tabs (~index/content-type-tabs
            :posts-href posts-href :pages-href pages-href
            :hx-select hx-select :posts-cls posts-cls :pages-cls pages-cls)
          :toggle (~shared:misc/view-toggle
            :list-href list-href :tile-href tile-href :hx-select hx-select
            :list-cls list-cls :tile-cls tile-cls :storage-key "blog_view"
            :list-svg (~shared:misc/list-svg) :tile-svg (~shared:misc/tile-svg))
          :grid-cls grid-cls
          :cards (<>
            (map (lambda (card)
              (if (= view "tile")
                (~cards/tile
                  :href (get card "href") :hx-select hx-select
                  :feature-image (get card "feature_image")
                  :title (get card "title") :is-draft (get card "is_draft")
                  :publish-requested (get card "publish_requested")
                  :status-timestamp (get card "status_timestamp")
                  :excerpt (get card "excerpt")
                  :tags (get card "tags") :authors (get card "authors"))
                (~cards/index
                  :slug (get card "slug") :href (get card "href") :hx-select hx-select
                  :title (get card "title") :feature-image (get card "feature_image")
                  :excerpt (get card "excerpt") :is-draft (get card "is_draft")
                  :publish-requested (get card "publish_requested")
                  :status-timestamp (get card "status_timestamp")
                  :has-like (get card "has_like") :liked (get card "liked")
                  :like-url (get card "like_url") :csrf-token (get card "csrf_token")
                  :tags (get card "tags") :authors (get card "authors")
                  :widget (get card "widget"))))
              (or cards (list)))
            (~index/sentinel
              :page page :total-pages total-pages
              :current-local-href current-local-href)))))))

;; Sentinel for blog index infinite scroll
(defcomp ~index/sentinel (&key page total-pages current-local-href)
  (when (< page total-pages)
    (let* ((next-url (str current-local-href "?page=" (+ page 1))))
      (~shared:misc/sentinel-desktop
        :id (str "sentinel-" page "-d")
        :next-url next-url
        :hyperscript "init if not me.dataset.retryMs then set me.dataset.retryMs to 1000 end on htmx:beforeRequest(event) add .hidden to .js-neterr in me remove .hidden from .js-loading in me remove .opacity-100 from me add .opacity-0 to me set trig to null if event.detail and event.detail.triggeringEvent then set trig to event.detail.triggeringEvent end if trig and trig.type is 'intersect' set scroller to the closest .js-grid-viewport if scroller is null then halt end if scroller.scrollTop < 20 then halt end end def backoff() set ms to me.dataset.retryMs if ms > 30000 then set ms to 30000 end add .hidden to .js-loading in me remove .hidden from .js-neterr in me remove .opacity-0 from me add .opacity-100 to me wait ms ms trigger sentinel:retry set ms to ms * 2 if ms > 30000 then set ms to 30000 end set me.dataset.retryMs to ms end on htmx:sendError call backoff() on htmx:responseError call backoff() on htmx:timeout call backoff()"))))

;; Blog index action buttons — replaces _action_buttons_sx
(defcomp ~index/actions (&key is-admin has-user hx-select draft-count drafts
                                   new-post-href new-page-href current-local-href)
  (~filters/action-buttons-wrapper
    :inner (<>
      (when is-admin
        (<>
          (~filters/action-button
            :href new-post-href :hx-select hx-select
            :btn-class "px-3 py-1 rounded bg-stone-700 text-white text-sm hover:bg-stone-800 transition-colors"
            :title "New Post" :icon-class "fa fa-plus mr-1" :label " New Post")
          (~filters/action-button
            :href new-page-href :hx-select hx-select
            :btn-class "px-3 py-1 rounded bg-blue-600 text-white text-sm hover:bg-blue-700 transition-colors"
            :title "New Page" :icon-class "fa fa-plus mr-1" :label " New Page")))
      (when (and has-user (or draft-count drafts))
        (if drafts
          (~filters/drafts-button
            :href current-local-href :hx-select hx-select
            :btn-class "px-3 py-1 rounded bg-stone-700 text-white text-sm hover:bg-stone-800 transition-colors"
            :title "Hide Drafts" :label " Drafts " :draft-count (str draft-count))
          (let* ((on-href (str current-local-href
                   (if (contains? current-local-href "?") "&" "?") "drafts=1")))
            (~filters/drafts-button-amber
              :href on-href :hx-select hx-select
              :btn-class "px-3 py-1 rounded bg-amber-600 text-white text-sm hover:bg-amber-700 transition-colors"
              :title "Show Drafts" :label " Drafts " :draft-count (str draft-count))))))))

;; Tag groups filter — replaces _tag_groups_filter_sx
(defcomp ~index/tag-groups-filter (&key tag-groups is-any-group hx-select)
  (~filters/nav
    :items (<>
      (~filters/any-topic
        :cls (if is-any-group
          "bg-stone-900 text-white border-stone-900"
          "bg-white text-stone-600 border-stone-300 hover:bg-stone-50")
        :hx-select hx-select)
      (map (lambda (grp)
        (let* ((is-on (get grp "is_selected"))
               (cls (if is-on
                 "bg-stone-900 text-white border-stone-900"
                 "bg-white text-stone-600 border-stone-300 hover:bg-stone-50"))
               (fi (get grp "feature_image"))
               (colour (get grp "colour"))
               (name (get grp "name"))
               (icon (if fi
                 (~filters/group-icon-image :src fi :name name)
                 (~filters/group-icon-color
                   :style (if colour
                     (str "background-color: " colour "; color: white;")
                     "background-color: #e7e5e4; color: #57534e;")
                   :initial (slice (or name "?") 0 1)))))
          (~filters/group-li
            :cls cls :hx-get (str "?group=" (get grp "slug") "&page=1")
            :hx-select hx-select :icon icon
            :name name :count (str (get grp "post_count")))))
        (or tag-groups (list))))))

;; Authors filter — replaces _authors_filter_sx
(defcomp ~index/authors-filter (&key authors is-any-author hx-select)
  (~filters/nav
    :items (<>
      (~filters/any-author
        :cls (if is-any-author
          "bg-stone-900 text-white border-stone-900"
          "bg-white text-stone-600 border-stone-300 hover:bg-stone-50")
        :hx-select hx-select)
      (map (lambda (a)
        (let* ((is-on (get a "is_selected"))
               (cls (if is-on
                 "bg-stone-900 text-white border-stone-900"
                 "bg-white text-stone-600 border-stone-300 hover:bg-stone-50"))
               (img (get a "profile_image")))
          (~filters/author-li
            :cls cls :hx-get (str "?author=" (get a "slug") "&page=1")
            :hx-select hx-select
            :icon (when img (~filters/author-icon :src img :name (get a "name")))
            :name (get a "name")
            :count (str (get a "published_post_count")))))
        (or authors (list))))))

;; Blog index aside — replaces _blog_aside_sx
(defcomp ~index/aside-content (&key is-admin has-user hx-select draft-count drafts
                                         new-post-href new-page-href current-local-href
                                         tag-groups authors is-any-group is-any-author)
  (~index/aside
    :search (~shared:controls/search-desktop)
    :action-buttons (~index/actions
      :is-admin is-admin :has-user has-user :hx-select hx-select
      :draft-count draft-count :drafts drafts
      :new-post-href new-post-href :new-page-href new-page-href
      :current-local-href current-local-href)
    :tag-groups-filter (~index/tag-groups-filter
      :tag-groups tag-groups :is-any-group is-any-group :hx-select hx-select)
    :authors-filter (~index/authors-filter
      :authors authors :is-any-author is-any-author :hx-select hx-select)))

;; Blog index mobile filter — replaces _blog_filter_sx
(defcomp ~index/filter-content (&key is-admin has-user hx-select draft-count drafts
                                          new-post-href new-page-href current-local-href
                                          tag-groups authors is-any-group is-any-author
                                          tg-summary au-summary)
  (~shared:controls/mobile-filter
    :filter-summary (<>
      (~shared:controls/search-mobile)
      (when (not (= tg-summary ""))
        (~filters/summary :text tg-summary))
      (when (not (= au-summary ""))
        (~filters/summary :text au-summary)))
    :action-buttons (~index/actions
      :is-admin is-admin :has-user has-user :hx-select hx-select
      :draft-count draft-count :drafts drafts
      :new-post-href new-post-href :new-page-href new-page-href
      :current-local-href current-local-href)
    :filter-details (<>
      (~index/tag-groups-filter
        :tag-groups tag-groups :is-any-group is-any-group :hx-select hx-select)
      (~index/authors-filter
        :authors authors :is-any-author is-any-author :hx-select hx-select))))
