# ============================================================
#  audit.py — Rapport C/U/F (Check / Update / Future)
#  rolax1212 v1.0 by Roland
# ============================================================

import json
import re
from .ui  import console, ok, info, warn, err, separateur, afficher_audit
from .llm import demander


PROMPT_AUDIT = """Tu es un expert en développement logiciel.
Analyse ce projet et génère un rapport JSON structuré.

{contexte}

Génère UNIQUEMENT un objet JSON valide (pas de texte avant ou après) avec ce format exact :
{{
  "check": [
    {{"fichier": "nom.php", "probleme": "description courte du bug", "corrige": false}}
  ],
  "update": [
    "amélioration concrète à faire maintenant"
  ],
  "future": [
    "fonctionnalité à ajouter plus tard"
  ]
}}

Règles :
- "check" : bugs réels (syntaxe cassée, sécurité critique, logique erronée)
- "update" : améliorations de qualité (validation, hashage, protection CSRF, etc.)
- "future" : nouvelles fonctionnalités utiles au projet
- Maximum 5 items par section
- Sois précis et concis
- Réponds UNIQUEMENT avec le JSON, rien d'autre
"""


def generer_rapport(fichiers, modele):
    """
    Analyse le projet et retourne le rapport C/U/F.
    Retourne un dict {check, update, future}.
    """
    from .projet import construire_contexte

    if not fichiers:
        return {"check": [], "update": [], "future": []}

    info("Analyse du projet en cours...")

    contexte = construire_contexte(fichiers)
    prompt   = PROMPT_AUDIT.format(contexte=contexte)

    messages = [{"role": "user", "content": prompt}]

    # Pas de stream pour parser le JSON proprement
    reponse = demander(messages, modele, stream=False, timeout=120)

    if not reponse:
        warn("Impossible d'obtenir le rapport d'audit.")
        return {"check": [], "update": [], "future": []}

    return _parser_rapport(reponse)


def _parser_rapport(reponse):
    """Parse la réponse JSON du LLM."""
    # Cherche le JSON dans la réponse (au cas où le LLM ajoute du texte)
    match = re.search(r'\{.*\}', reponse, re.DOTALL)
    if match:
        json_str = match.group(0)
    else:
        json_str = reponse.strip()

    try:
        data = json.loads(json_str)
        return {
            "check":  data.get("check",  []),
            "update": data.get("update", []),
            "future": data.get("future", [])
        }
    except json.JSONDecodeError:
        # Fallback : extrait manuellement les sections
        return _parser_fallback(reponse)


def _parser_fallback(reponse):
    """Fallback si le JSON est mal formé — extrait les listes à puces."""
    rapport = {"check": [], "update": [], "future": []}
    section = None

    for ligne in reponse.splitlines():
        l = ligne.strip().lower()

        if "check" in l or "bug" in l or "erreur" in l:
            section = "check"
        elif "update" in l or "amélioration" in l or "amelioration" in l:
            section = "update"
        elif "future" in l or "fonctionnalit" in l or "suggestion" in l:
            section = "future"
        elif section and (ligne.strip().startswith("-") or ligne.strip().startswith("•")):
            texte = ligne.strip().lstrip("-•").strip()
            if texte and len(texte) > 3:
                if section == "check":
                    rapport["check"].append({"fichier": "?", "probleme": texte, "corrige": False})
                else:
                    rapport[section].append(texte)

    return rapport


def corriger_bugs(rapport, path_projet, fichiers, modele):
    """
    Tente de corriger automatiquement les bugs du rapport CHECK.
    Met à jour rapport["check"][i]["corrige"] = True si réussi.
    """
    from .projet import sauvegarder, extraire_blocs
    from pathlib import Path

    bugs = rapport.get("check", [])
    if not bugs:
        ok("Aucun bug à corriger.")
        return rapport

    for i, bug in enumerate(bugs):
        nom_fichier = bug.get("fichier", "")
        probleme    = bug.get("probleme", "")

        if not nom_fichier or nom_fichier == "?":
            continue

        chemin = Path(path_projet) / nom_fichier
        if not chemin.exists():
            continue

        contenu = chemin.read_text(encoding="utf-8")
        lang    = chemin.suffix.lstrip(".")

        info(f"Correction de {nom_fichier} — {probleme[:50]}...")

        prompt = (
            f"Ce fichier {lang.upper()} a un bug : {probleme}\n\n"
            f"```{lang}\n{contenu}\n```\n\n"
            f"Corrige UNIQUEMENT ce bug. Retourne UNIQUEMENT le code corrigé complet "
            f"dans un bloc ```{lang} ... ```. Pas d'explication."
        )

        messages = [{"role": "user", "content": prompt}]
        reponse  = demander(messages, modele, stream=False, timeout=120)

        if not reponse:
            continue

        blocs = extraire_blocs(reponse)
        if blocs and len(blocs[0]["code"]) > 20:
            sauvegarder(chemin, blocs[0]["code"])
            fichiers[nom_fichier]         = blocs[0]["code"]
            rapport["check"][i]["corrige"] = True
            ok(f"{nom_fichier} — corrigé")
        else:
            warn(f"{nom_fichier} — correction manuelle requise")

    return rapport
