"""Collecteur du Sénat — liste chronologique des lois promulguées.

C'est le repli principal lorsque l'API Légifrance est indisponible, et un
contrôle croisé lorsqu'elle fonctionne. La page rend, pour chaque loi
promulguée de la session, son numéro, sa date, son intitulé complet et le lien
vers son dossier législatif.

L'adresse indiquée au §5.1 du cahier des charges — `senat.fr/lois/index.html` —
renvoie une erreur 404 depuis la refonte du site. L'équivalent fonctionnel est
`senat.fr/dossiers-legislatifs/lois-promulguees.html`, vérifié le 25 juillet
2026 : 51 lois y figuraient, dont les 27 de la fenêtre de veille.
"""

from __future__ import annotations

import re

from selectolax.parser import HTMLParser

from pipeline.collecteurs.base import Collecteur, ResultatCollecte, TexteCollecte
from pipeline.collecteurs.http import ClientHttp
from pipeline.journal import logger
from pipeline.modeles import Confiance, Evenement, Source, Statut, Tier, TypeEtape, TypeTexte
from pipeline.parseurs.dates_fr import lire_date

log = logger("collecteur.senat")

BASE = "https://www.senat.fr"
URL_LOIS_PROMULGUEES = f"{BASE}/dossiers-legislatifs/lois-promulguees.html"

# « Loi n° 2026-650 du 23 juillet 2026 relative au renforcement… »
# « Loi organique n° 2026-410 du 28 mai 2026 … »
_INTITULE = re.compile(
    r"Loi\s+(organique\s+)?n°\s*(\d{4}-\d{1,4})\s+du\s+"
    r"(\d{1,2}(?:er)?\s+\w+\.?\s+\d{4})\s+(.*)",
    re.IGNORECASE | re.DOTALL,
)


class CollecteurSenat(Collecteur):
    nom = "senat"

    def __init__(self, client: ClientHttp, *, annees: tuple[int, ...] = (2026,)) -> None:
        self.client = client
        self.annees = annees

    def _collecter(self) -> ResultatCollecte:
        resultat = ResultatCollecte(collecteur=self.nom)

        reponse = self.client.get(URL_LOIS_PROMULGUEES)
        if not reponse.a_reussi:
            raise RuntimeError(f"HTTP {reponse.code} sur {URL_LOIS_PROMULGUEES}")

        document = HTMLParser(reponse.texte)
        vus: set[str] = set()

        for ancre in document.css("a"):
            libelle = " ".join(ancre.text(separator=" ", strip=True).split())
            texte = self._lire_intitule(libelle, ancre.attributes.get("href"))
            if texte is None or texte.numero_officiel in vus:
                continue
            vus.add(texte.numero_officiel)
            resultat.textes.append(texte)

        log.debug("lois promulguées relevées", nombre=len(resultat.textes))
        return resultat

    def _lire_intitule(self, libelle: str, href: str | None) -> TexteCollecte | None:
        correspondance = _INTITULE.search(libelle)
        if not correspondance:
            return None

        organique = bool(correspondance.group(1))
        numero = correspondance.group(2)
        if int(numero.split("-")[0]) not in self.annees:
            return None

        date_promulgation = lire_date(correspondance.group(3))
        if date_promulgation is None:
            return None

        # Le libellé se termine par un état (« parue », « en cours »)
        # qu'il ne faut pas confondre avec l'objet de la loi.
        objet = re.split(r"\s+(?:parue|en cours)\b", correspondance.group(4))[0].strip(" .;")
        titre = (
            f"LOI {'organique ' if organique else ''}n° {numero} "
            f"du {correspondance.group(3)} {objet}"
        )

        url = _absolu(href) or URL_LOIS_PROMULGUEES

        return TexteCollecte(
            titre=" ".join(titre.split()),
            source_url=url,
            collecteur=self.nom,
            numero_officiel=numero,
            type=TypeTexte.LOI_ORGANIQUE if organique else TypeTexte.LOI,
            statut=Statut.PROMULGUEE,
            date_promulgation=date_promulgation,
            evenements=[
                Evenement(
                    date_evenement=date_promulgation,
                    type_etape=TypeEtape.PROMULGATION,
                    description=f"Loi promulguée n° {numero}, relevée sur la liste du Sénat",
                    source_url=url,
                )
            ],
            sources=[
                Source(
                    url=url,
                    titre=" ".join(titre.split())[:280],
                    editeur="Sénat",
                    date_publication=date_promulgation,
                    tier=Tier.T1,
                    confiance=Confiance.HIGH,
                    marqueur=f"senat-{numero}",
                    fichier_origine="collecteur:senat",
                )
            ],
        )


def _absolu(href: str | None) -> str | None:
    if not href:
        return None
    if href.startswith("http"):
        return href
    if href.startswith("/"):
        return BASE + href
    return None
