(defcomp ~tl-link (&key href label) (a :href href label))

(defcomp
  ~tl-badge
  (&key href count)
  (a :href href (span (if count count "0"))))

(defcomp
  ~tl-error
  (&key errnum message image)
  (div
    :class "error"
    (h1 errnum)
    (p message)
    (when image (img :src image))))

(defcomp ~tl-wrapper (&key class &rest children) (div :class class children))

(defcomp ~tl-inner (&key text) (span :class "inner" text))

(defcomp
  ~tl-outer
  (&key label)
  (div :class "outer" (~tl-inner :text label)))

(defcomp
  ~tl-toggle
  (&key show-extra)
  (div (p "always") (when show-extra (p "extra"))))

(defcomp ~tl-clear (&key id) (div :id id))

(defsuite
  "layout-link-pattern"
  (deftest
    "renders anchor with href and label"
    (let
      ((html (render-to-html (quote (~tl-link :href "/about" :label "About")) {})))
      (assert-true (string-contains? html "/about"))
      (assert-true (string-contains? html "About")))))

(defsuite
  "layout-badge-pattern"
  (deftest
    "renders badge with count"
    (let
      ((html (render-to-html (quote (~tl-badge :href "/cart" :count "3")) {})))
      (assert-true (string-contains? html "3"))
      (assert-true (string-contains? html "/cart"))))
  (deftest
    "renders default count when nil"
    (let
      ((html (render-to-html (quote (~tl-badge :href "/cart")) {})))
      (assert-true (string-contains? html "0")))))

(defsuite
  "layout-error-pattern"
  (deftest
    "renders error with number and message"
    (let
      ((html (render-to-html (quote (~tl-error :errnum "404" :message "Not Found")) {})))
      (assert-true (string-contains? html "404"))
      (assert-true (string-contains? html "Not Found"))))
  (deftest
    "renders with image when provided"
    (let
      ((html (render-to-html (quote (~tl-error :errnum "500" :message "Error" :image "/err.png")) {})))
      (assert-true (string-contains? html "500"))
      (assert-true (string-contains? html "/err.png"))))
  (deftest
    "omits image when nil"
    (let
      ((html (render-to-html (quote (~tl-error :errnum "404" :message "Missing")) {})))
      (assert-false (string-contains? html "img")))))

(defsuite
  "layout-children-pattern"
  (deftest
    "renders children inside wrapper"
    (let
      ((html (render-to-html (quote (~tl-wrapper :class "box" (p "inner"))) {})))
      (assert-true (string-contains? html "inner"))
      (assert-true (string-contains? html "box"))))
  (deftest
    "renders multiple children"
    (let
      ((html (render-to-html (quote (~tl-wrapper :class "section" (h2 "Title") (p "Body"))) {})))
      (assert-true (string-contains? html "Title"))
      (assert-true (string-contains? html "Body")))))

(defsuite
  "layout-nesting-pattern"
  (deftest
    "nested component calls"
    (let
      ((html (render-to-html (quote (~tl-outer :label "nested")) {})))
      (assert-true (string-contains? html "nested"))
      (assert-true (string-contains? html "inner"))
      (assert-true (string-contains? html "outer")))))

(defsuite
  "layout-conditional-pattern"
  (deftest
    "shows extra when true"
    (let
      ((html (render-to-html (quote (~tl-toggle :show-extra true)) {})))
      (assert-true (string-contains? html "always"))
      (assert-true (string-contains? html "extra"))))
  (deftest
    "hides extra when false"
    (let
      ((html (render-to-html (quote (~tl-toggle :show-extra false)) {})))
      (assert-true (string-contains? html "always"))
      (assert-false (string-contains? html "extra")))))

(defsuite
  "layout-clear-pattern"
  (deftest
    "renders div with id"
    (let
      ((html (render-to-html (quote (~tl-clear :id "sidebar")) {})))
      (assert-true (string-contains? html "sidebar")))))
