"""Détection de la pertinence guadeloupéenne et ultramarine d'un texte.

Le tableau A de l'annexe cote lui-même les 27 lois promulguées ; le tableau B
ne cote pas les textes en cours. Pour ces derniers, la cotation est déduite du
vocabulaire employé par le rapport, avec des poids déclarés dans
`pipeline/config.yaml`.

Toute cotation obtenue ainsi est signalée : le texte porte `a_verifier = 1` et
un motif explicite. L'interface l'affiche comme telle. Une cotation déduite
n'est pas une cotation établie.
"""

from __future__ import annotations

import functools
import re
from dataclasses import dataclass

import yaml

from pipeline import chemins
from pipeline.modeles import Pertinence
from pipeline.parseurs.dates_fr import sans_accents


@dataclass(slots=True)
class Cotation:
    """Résultat d'une détection, avec ce qui l'a motivée."""

    pertinence: Pertinence | None
    score: int
    expressions: list[str]

    @property
    def note(self) -> str | None:
        if not self.expressions:
            return None
        return "Détecté d'après : " + ", ".join(self.expressions[:6])


@functools.lru_cache(maxsize=1)
def _configuration() -> dict:
    return yaml.safe_load(chemins.CONFIG.read_text(encoding="utf-8"))


@functools.lru_cache(maxsize=1)
def _motifs() -> list[tuple[re.Pattern[str], str, int]]:
    """Compile un motif par expression, ancré sur des frontières de mot."""
    expressions = _configuration()["guadeloupe"]["expressions"]
    compiles: list[tuple[re.Pattern[str], str, int]] = []

    for expression, poids in expressions.items():
        plat = sans_accents(str(expression)).lower()
        compiles.append((re.compile(rf"(?<!\w){re.escape(plat)}\w{{0,3}}(?!\w)"), plat, int(poids)))

    # Les expressions les plus lourdes d'abord : le compte-rendu cite en
    # priorité ce qui a réellement décidé de la cotation.
    compiles.sort(key=lambda triplet: -triplet[2])
    return compiles


def coter(*fragments: str | None) -> Cotation:
    """Cote la pertinence guadeloupéenne d'un ensemble de fragments de texte."""
    plat = sans_accents(" ".join(f for f in fragments if f)).lower()
    if not plat.strip():
        return Cotation(pertinence=None, score=0, expressions=[])

    score = 0
    trouvees: list[str] = []

    for motif, expression, poids in _motifs():
        if motif.search(plat):
            score += poids
            trouvees.append(expression)

    seuils = _configuration()["guadeloupe"]["seuils"]
    if score >= seuils["forte"]:
        pertinence = Pertinence.FORTE
    elif score >= seuils["moyenne"]:
        pertinence = Pertinence.MOYENNE
    elif score >= seuils["faible"]:
        pertinence = Pertinence.FAIBLE
    else:
        pertinence = None

    return Cotation(pertinence=pertinence, score=score, expressions=trouvees)


MOTIF_VERIFICATION = (
    "Pertinence Guadeloupe déduite automatiquement : l'annexe du rapport ne "
    "cote que les lois promulguées, pas les textes encore en discussion."
)
