;; Events entry card components (all events / page summary)

;; ---------------------------------------------------------------------------
;; State badges — cond maps state string to class + label
;; ---------------------------------------------------------------------------

(defcomp ~entries/entry-state-badge (&key state)
  (~shared:misc/badge
    :cls (cond
      ((= state "confirmed") "bg-emerald-100 text-emerald-800")
      ((= state "provisional") "bg-amber-100 text-amber-800")
      ((= state "ordered") "bg-sky-100 text-sky-800")
      ((= state "pending") "bg-stone-100 text-stone-700")
      ((= state "declined") "bg-red-100 text-red-800")
      (true "bg-stone-100 text-stone-700"))
    :label (cond
      ((= state "confirmed") "Confirmed")
      ((= state "provisional") "Provisional")
      ((= state "ordered") "Ordered")
      ((= state "pending") "Pending")
      ((= state "declined") "Declined")
      (true (or state "Unknown")))))

(defcomp ~entries/entry-state-badge-lg (&key state)
  (span :class (str "inline-flex items-center rounded-full px-3 py-1 text-sm font-medium "
                (cond
                  ((= state "confirmed") "bg-emerald-100 text-emerald-800")
                  ((= state "provisional") "bg-amber-100 text-amber-800")
                  ((= state "ordered") "bg-sky-100 text-sky-800")
                  ((= state "pending") "bg-stone-100 text-stone-700")
                  ((= state "declined") "bg-red-100 text-red-800")
                  (true "bg-stone-100 text-stone-700")))
    (cond
      ((= state "confirmed") "Confirmed")
      ((= state "provisional") "Provisional")
      ((= state "ordered") "Ordered")
      ((= state "pending") "Pending")
      ((= state "declined") "Declined")
      (true (or state "Unknown")))))

(defcomp ~entries/ticket-state-badge (&key state)
  (~shared:misc/badge
    :cls (cond
      ((= state "confirmed") "bg-emerald-100 text-emerald-800")
      ((= state "checked_in") "bg-blue-100 text-blue-800")
      ((= state "reserved") "bg-amber-100 text-amber-800")
      ((= state "cancelled") "bg-red-100 text-red-800")
      (true "bg-stone-100 text-stone-700"))
    :label (cond
      ((= state "confirmed") "Confirmed")
      ((= state "checked_in") "Checked in")
      ((= state "reserved") "Reserved")
      ((= state "cancelled") "Cancelled")
      (true (or state "Unknown")))))

(defcomp ~entries/ticket-state-badge-lg (&key state)
  (span :class (str "inline-flex items-center rounded-full px-3 py-1 text-sm font-medium "
                (cond
                  ((= state "confirmed") "bg-emerald-100 text-emerald-800")
                  ((= state "checked_in") "bg-blue-100 text-blue-800")
                  ((= state "reserved") "bg-amber-100 text-amber-800")
                  ((= state "cancelled") "bg-red-100 text-red-800")
                  (true "bg-stone-100 text-stone-700")))
    (cond
      ((= state "confirmed") "Confirmed")
      ((= state "checked_in") "Checked in")
      ((= state "reserved") "Reserved")
      ((= state "cancelled") "Cancelled")
      (true (or state "Unknown")))))


;; ---------------------------------------------------------------------------
;; Entry card components
;; ---------------------------------------------------------------------------

(defcomp ~entries/entry-title-linked (&key href name)
  (a :href href :class "hover:text-emerald-700"
    (h2 :class "text-lg font-semibold text-stone-900" name)))

(defcomp ~entries/entry-title-plain (&key name)
  (h2 :class "text-lg font-semibold text-stone-900" name))

(defcomp ~entries/entry-title-tile-linked (&key href name)
  (a :href href :class "hover:text-emerald-700"
    (h2 :class "text-base font-semibold text-stone-900 line-clamp-2" name)))

(defcomp ~entries/entry-title-tile-plain (&key name)
  (h2 :class "text-base font-semibold text-stone-900 line-clamp-2" name))

(defcomp ~entries/entry-page-badge (&key href title)
  (a :href href :class "inline-block px-2 py-0.5 rounded-full text-xs font-medium bg-amber-100 text-amber-800 hover:bg-amber-200" title))

(defcomp ~entries/entry-cal-badge (&key name)
  (span :class "inline-block px-2 py-0.5 rounded-full text-xs font-medium bg-sky-100 text-sky-700" name))

(defcomp ~entries/entry-time-linked (&key href date-str)
  (<> (a :href href :class "hover:text-stone-700" date-str) " · "))

(defcomp ~entries/entry-time-plain (&key date-str)
  (<> (span date-str) " · "))

(defcomp ~entries/entry-cost (&key cost)
  (div :class "mt-1 text-sm font-medium text-green-600" cost))

(defcomp ~entries/entry-card (&key title badges time-parts cost widget)
  (article :class "rounded-xl bg-white shadow-sm border border-stone-200 p-4"
    (div :class "flex flex-col sm:flex-row sm:items-start justify-between gap-3"
      (div :class "flex-1 min-w-0"
        title
        (div :class "flex flex-wrap items-center gap-1.5 mt-1" badges)
        (div :class "mt-1 text-sm text-stone-500" time-parts)
        cost)
      widget)))

(defcomp ~entries/entry-card-tile (&key title badges time cost widget)
  (article :class "rounded-xl bg-white shadow-sm border border-stone-200 overflow-hidden"
    (div :class "p-3"
      title
      (div :class "flex flex-wrap items-center gap-1 mt-1" badges)
      (div :class "mt-1 text-xs text-stone-500" time)
      cost)
    widget))

(defcomp ~entries/entry-tile-widget-wrapper (&key widget)
  (div :class "border-t border-stone-100 px-3 py-2" widget))

(defcomp ~entries/entry-widget-wrapper (&key widget)
  (div :class "shrink-0" widget))

(defcomp ~entries/date-separator (&key date-str)
  (div :class "pt-2 pb-1"
    (h3 :class "text-sm font-semibold text-stone-500 uppercase tracking-wide" date-str)))

(defcomp ~entries/grid (&key grid-cls cards)
  (div :class grid-cls cards))

(defcomp ~entries/main-panel-body (&key toggle body)
  (<> toggle body (div :class "pb-8")))


;; ---------------------------------------------------------------------------
;; Composition defcomps — receive data, compose entry card trees
;; ---------------------------------------------------------------------------

;; Ticket widget from data — replaces _ticket_widget_html Python composition
(defcomp ~entries/tw-widget-from-data (&key entry-id price qty ticket-url csrf)
  (~page/tw-widget :entry-id (str entry-id) :price price
    :inner (if (= (or qty 0) 0)
      (~page/tw-form :ticket-url ticket-url :target (str "#page-ticket-" entry-id)
        :csrf csrf :entry-id (str entry-id) :count-val "1"
        :btn (~page/tw-cart-plus))
      (<>
        (~page/tw-form :ticket-url ticket-url :target (str "#page-ticket-" entry-id)
          :csrf csrf :entry-id (str entry-id) :count-val (str (- qty 1))
          :btn (~page/tw-minus))
        (~page/tw-cart-icon :qty (str qty))
        (~page/tw-form :ticket-url ticket-url :target (str "#page-ticket-" entry-id)
          :csrf csrf :entry-id (str entry-id) :count-val (str (+ qty 1))
          :btn (~page/tw-plus))))))

;; Entry card (list view) from data
(defcomp
  ~entries/entry-card-from-data
  (&key
    entry-href
    name
    day-href
    page-badge-href
    page-badge-title
    cal-name
    date-str
    start-time
    end-time
    is-page-scoped
    cost
    has-ticket
    ticket-data)
  (~entries/entry-card
    :title (if
      entry-href
      (~entries/entry-title-linked :href entry-href :name name)
      (~entries/entry-title-plain :name name))
    :badges (<>
      (when
        page-badge-title
        (~entries/entry-page-badge
          :href page-badge-href
          :title page-badge-title))
      (when cal-name (~entries/entry-cal-badge :name cal-name)))
    :time-parts (<>
      (when
        (and day-href (not is-page-scoped))
        (~entries/entry-time-linked :href day-href :date-str date-str))
      (when
        (and (not day-href) (not is-page-scoped) date-str)
        (~entries/entry-time-plain :date-str date-str))
      start-time
      (when end-time (str " – " end-time)))
    :cost (when cost (~entries/entry-cost :cost cost))
    :widget (when
      has-ticket
      (let-match
        {:csrf csrf :entry-id entry-id :qty qty :price price :ticket-url ticket-url}
        ticket-data
        (~entries/entry-widget-wrapper
          :widget (~entries/tw-widget-from-data
            :entry-id entry-id
            :price price
            :qty qty
            :ticket-url ticket-url
            :csrf csrf))))))

;; Entry card (tile view) from data
(defcomp
  ~entries/entry-card-tile-from-data
  (&key
    entry-href
    name
    day-href
    page-badge-href
    page-badge-title
    cal-name
    date-str
    time-str
    cost
    has-ticket
    ticket-data)
  (~entries/entry-card-tile
    :title (if
      entry-href
      (~entries/entry-title-tile-linked :href entry-href :name name)
      (~entries/entry-title-tile-plain :name name))
    :badges (<>
      (when
        page-badge-title
        (~entries/entry-page-badge
          :href page-badge-href
          :title page-badge-title))
      (when cal-name (~entries/entry-cal-badge :name cal-name)))
    :time time-str
    :cost (when cost (~entries/entry-cost :cost cost))
    :widget (when
      has-ticket
      (let-match
        {:csrf csrf :entry-id entry-id :qty qty :price price :ticket-url ticket-url}
        ticket-data
        (~entries/entry-tile-widget-wrapper
          :widget (~entries/tw-widget-from-data
            :entry-id entry-id
            :price price
            :qty qty
            :ticket-url ticket-url
            :csrf csrf))))))

;; Entry cards list (with date separators + sentinel) from data
(defcomp
  ~entries/entry-cards-from-data
  (&key items view page has-more next-url)
  (<>
    (map
      (lambda
        (item)
        (let-match
          {:date-str date-str :time-str time-str :has-ticket has-ticket :is-separator is-separator :ticket-data ticket-data :day-href day-href :page-badge-title page-badge-title :entry-href entry-href :start-time start-time :end-time end-time :is-page-scoped is-page-scoped :page-badge-href page-badge-href :cal-name cal-name :cost cost :name name}
          item
          (if
            is-separator
            (~entries/date-separator :date-str date-str)
            (if
              (= view "tile")
              (~entries/entry-card-tile-from-data
                :entry-href entry-href
                :name name
                :day-href day-href
                :page-badge-href page-badge-href
                :page-badge-title page-badge-title
                :cal-name cal-name
                :date-str date-str
                :time-str time-str
                :cost cost
                :has-ticket has-ticket
                :ticket-data ticket-data)
              (~entries/entry-card-from-data
                :entry-href entry-href
                :name name
                :day-href day-href
                :page-badge-href page-badge-href
                :page-badge-title page-badge-title
                :cal-name cal-name
                :date-str date-str
                :start-time start-time
                :end-time end-time
                :is-page-scoped is-page-scoped
                :cost cost
                :has-ticket has-ticket
                :ticket-data ticket-data)))))
      (or items (list)))
    (when
      has-more
      (~shared:misc/sentinel-simple
        :id (str "sentinel-" page)
        :next-url next-url))))

;; Events main panel (toggle + cards grid) from data
(defcomp ~entries/main-panel-from-data (&key toggle items view page has-more next-url)
  (~entries/main-panel-body
    :toggle toggle
    :body (if items
      (~entries/grid
        :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")
        :cards (~entries/entry-cards-from-data
          :items items :view view :page page
          :has-more has-more :next-url next-url))
      (~shared:misc/empty-state :icon "fa fa-calendar-xmark"
        :message "No upcoming events"
        :cls "px-3 py-12 text-center text-stone-400"))))
