"""Exercice fictif R3 : oracle explicite et quatre défauts ciblés.

Python 3, bibliothèque standard uniquement. Aucune connexion ni écriture.
Ce modèle isolé ne constitue pas un moteur d'autorisation de production.
"""
from dataclasses import dataclass, replace


@dataclass(frozen=True)
class Demande:
    montant_centimes: int = 100000
    responsable: bool = True
    societe_acteur: str = "A"
    societe_demande: str = "A"
    etat: str = "soumise"


def verdict(demande: Demande, defaut: str = "") -> str:
    if not demande.responsable:
        return "INTERDIT"
    if defaut != "sans_societe" and demande.societe_acteur != demande.societe_demande:
        return "INTERDIT"
    if defaut != "sans_etat" and demande.etat != "soumise":
        return "EN_ATTENTE"
    if demande.montant_centimes < 0 or (
        demande.montant_centimes == 0 and defaut != "zero_accepte"
    ):
        return "INVALIDE"
    limite = 99999 if defaut == "borne_stricte" else 100000
    return "APPROUVER" if demande.montant_centimes <= limite else "ESCALADER"


BASE = Demande()
# Attendus fixés par la règle R3, jamais calculés par verdict().
CAS = [
    ("A", replace(BASE, montant_centimes=99999), "APPROUVER"),
    ("B", BASE, "APPROUVER"),
    ("C", replace(BASE, montant_centimes=100001), "ESCALADER"),
    ("D", replace(BASE, responsable=False), "INTERDIT"),
    ("E", replace(BASE, societe_demande="B"), "INTERDIT"),
    ("F", replace(BASE, etat="brouillon"), "EN_ATTENTE"),
    ("G", replace(BASE, montant_centimes=0), "INVALIDE"),
]
DEFAUTS = {
    "borne_stricte": "B",
    "sans_societe": "E",
    "sans_etat": "F",
    "zero_accepte": "G",
}


def verifier() -> None:
    for nom, entree, attendu in CAS:
        obtenu = verdict(entree)
        if obtenu != attendu:
            raise AssertionError(f"Cas {nom}: attendu {attendu}, obtenu {obtenu}")
    print("7 cas conformes")
    for defaut, temoin in DEFAUTS.items():
        detecteurs = [nom for nom, entree, attendu in CAS if verdict(entree, defaut) != attendu]
        if detecteurs != [temoin]:
            raise AssertionError(f"Défaut {defaut}: attendu [{temoin}], obtenu {detecteurs}")
    print("4 défauts ciblés détectés : B, E, F, G")


if __name__ == "__main__":
    verifier()
