#!/usr/bin/env catnip
# Parsing HTML avec selectolax
# selectolax utilise le moteur Lexbor (C) - 10-30x plus rapide que BeautifulSoup
# Complète httpx : fetch (httpx) → parse (selectolax) → extract (Catnip)
#
# DEPS: selectolax

selectolax = import('selectolax.parser')

# Structs

struct SearchResult {
    title; href; score; meta;
    display(self) => {
        print(f"  [{self.score}] {self.title} -> {self.href}")
        print(f"           {self.meta}")
    }
}

struct TableRow {
    key; value;
    display(self) => { print(f"  {self.key} : {self.value}") }
}

# Extraction d'un résultat depuis un noeud HTML

extract_result = (node) => {
    title_node = node.css_first('a.title')
    SearchResult(
        title_node.text(),
        title_node.attributes['href'],
        node.attributes['data-score'],
        node.css_first('span.meta').text(),
    )
}

# HTML de test - une page de résultats fictive

HTML = '
<html>
<head><title>Résultats de recherche</title></head>
<body>
  <nav class="breadcrumb">
    <a href="/">Accueil</a> / <a href="/search">Recherche</a>
  </nav>
  <h1>3 résultats pour "catnip"</h1>
  <ul id="results">
    <li class="result" data-score="0.98">
      <a href="/doc/intro" class="title">Introduction à Catnip</a>
      <span class="meta">Guide - 5 min de lecture</span>
    </li>
    <li class="result" data-score="0.85">
      <a href="/doc/broadcast" class="title">Broadcasting</a>
      <span class="meta">Référence - 12 min de lecture</span>
    </li>
    <li class="result featured" data-score="0.72">
      <a href="/doc/patterns" class="title">Pattern Matching</a>
      <span class="meta">Tutoriel - 8 min de lecture</span>
    </li>
  </ul>
  <table class="stats">
    <tr><th>Métrique</th><th>Valeur</th></tr>
    <tr><td>Temps</td><td>0.042s</td></tr>
    <tr><td>Index</td><td>12,847 pages</td></tr>
  </table>
  <footer><p>Généré en 42ms</p></footer>
</body>
</html>
'

tree = selectolax.HTMLParser(HTML)

# Accès direct aux éléments structurels

print("⇒ Éléments structurels")
print(f"  <title>: {tree.css_first('title').text()}")
print(f"  <h1>: {tree.css_first('h1').text()}")

# Sélecteurs CSS - même syntaxe que les navigateurs

print()
print("⇒ Sélecteurs CSS")

# Par classe
results = tree.css('li.result')
print(f"  li.result: {len(results)} éléments")

# Par id
ul = tree.css_first('#results')
print(f"  #results tag: {ul.tag}")

# Combiné
featured = tree.css_first('li.featured a.title')
print(f"  li.featured a.title: {featured.text()}")

# Extraction de données structurées via broadcasting

print()
print("⇒ Extraction des résultats")
search_results = tree.css('li.result').[(n) => { extract_result(n) }]
search_results.[(r) => { r.display() }]

# Attributs et navigation

print()
print("⇒ Attributs")
links = tree.css('nav.breadcrumb a')
for a in links {
    print(f"  <a href=\"{a.attributes['href']}\">{a.text()}</a>")
}

# Parsing de table HTML via struct TableRow

print()
print("⇒ Table de stats")
rows = tree.css('table.stats tr')
table_rows = list()
for row in rows {
    cells = row.css('td')
    if len(cells) == 2 {
        table_rows.append(TableRow(cells[0].text(), cells[1].text()))
    }
}
table_rows.[(r) => { r.display() }]

# Texte brut (strip tags)

print()
print("⇒ Texte brut du footer")
footer = tree.css_first('footer')
print(f"  {footer.text(strip=True)}")

# Combinaison avec httpx (pattern complet)
# fetch = httpx.get("https://example.com")
# tree = selectolax.HTMLParser(fetch.text)
# data = tree.css("article h2").[text()]

print()
print("⇒ Terminé")