;; Bundle analyzer — live demonstration of dependency analysis + IO detection.
;; Shows per-page component bundles vs total, visualizing payload savings.
;; Drill down into each bundle to see component tree; expand to see SX source.
;; @css bg-green-100 text-green-800 bg-violet-600 bg-stone-200 text-violet-600 text-stone-600 text-green-600 rounded-full h-2.5 grid-cols-3 bg-blue-100 text-blue-800 bg-amber-100 text-amber-800 grid-cols-4 marker:text-stone-400 bg-blue-50 bg-amber-50 text-blue-700 text-amber-700 border-blue-200 border-amber-200 bg-blue-500 bg-amber-500
(defcomp (&key (pages :as list) (total-components :as number) (total-macros :as number)
                                        (pure-count :as number) (io-count :as number))
  (~docs/page :title "Page Bundle Analyzer"

    (p (~tw :tokens "text-stone-600 mb-6")
      "Live analysis of component dependency graphs and IO classification across all pages. "
      "Each bar shows how many of the "
      (strong (str total-components))
      " total components a page actually needs, computed by the "
      (a :href "/sx/(language.(spec.deps))" (~tw :tokens "text-violet-700 underline") "deps.sx")
      " transitive closure algorithm. "
      "Click a page to see its component tree; expand a component to see its SX source.")

    (div (~tw :tokens "mb-8 grid grid-cols-4 gap-4")
      (~analyzer/stat :label "Total Components" :value (str total-components)
                      :cls "text-violet-600")
      (~analyzer/stat :label "Total Macros" :value (str total-macros)
                      :cls "text-stone-600")
      (~analyzer/stat :label "Pure Components" :value (str pure-count)
                      :cls "text-blue-600")
      (~analyzer/stat :label "IO-Dependent" :value (str io-count)
                      :cls "text-amber-600"))

    (~docs/section :title "Per-Page Bundles" :id "bundles"
      (div (~tw :tokens "space-y-3")
        (map (fn (page)
          (~analyzer/row
            :name (get page "name")
            :path (get page "path")
            :needed (get page "needed")
            :direct (get page "direct")
            :total total-components
            :pct (get page "pct")
            :savings (get page "savings")
            :io-refs (get page "io-refs")
            :pure-in-page (get page "pure-in-page")
            :io-in-page (get page "io-in-page")
            :components (get page "components")))
          pages)))

    (~docs/section :title "How It Works" :id "how"
      (ol (~tw :tokens "list-decimal pl-5 space-y-2 text-stone-700")
        (li (strong "Scan: ") "Regex finds all " (code "(~plans/content-addressed-components/name") " patterns in the page's content expression.")
        (li (strong "Resolve: ") "Each referenced component's body AST is walked to find transitive " (code "~") " references.")
        (li (strong "Closure: ") "The full set is the union of direct + transitive deps, following chains through the component graph.")
        (li (strong "Bundle: ") "Only these component definitions are serialized into the page payload. Everything else is omitted.")
        (li (strong "IO detect: ") "Each component body is scanned for references to IO primitives (frag, query, service, etc.). Components with zero transitive IO refs are pure — safe for client rendering."))
      (p (~tw :tokens "mt-4 text-stone-600")
        "The analysis handles circular references (via seen-set), "
        "walks all branches of control flow (if/when/cond/case), "
        "and includes macro definitions shared across components."))))
