# ============================================================
#  git_manager.py — Gestion Git automatique
#  rolax1212 v2.0 by Roland
# ============================================================

import subprocess
from pathlib import Path
from .ui  import console, ok, info, warn, err, separateur, confirmer
from .llm import demander


# ============================================================
#  VERIFICATIONS
# ============================================================
def git_disponible():
    try:
        subprocess.run(["git", "--version"], capture_output=True, timeout=5)
        return True
    except FileNotFoundError:
        return False


def est_repo_git(path):
    return (Path(path) / ".git").exists()


def _run(cmd, cwd):
    r = subprocess.run(cmd, cwd=str(cwd), capture_output=True, text=True, timeout=30)
    return r.returncode, r.stdout.strip(), r.stderr.strip()


# ============================================================
#  INITIALISATION
# ============================================================
def init_git(path):
    """Initialise un repo git si pas encore fait."""
    path = Path(path)

    if not git_disponible():
        err("Git non installé. Installe Git : https://git-scm.com")
        return False

    if est_repo_git(path):
        info("Repo Git déjà initialisé.")
        return True

    code, out, err_msg = _run(["git", "init"], path)
    if code == 0:
        ok("Repo Git initialisé")

        # .gitignore si pas encore créé
        gitignore = path / ".gitignore"
        if not gitignore.exists():
            gitignore.write_text(
                "*.pyc\n__pycache__/\n.env\nvenv/\n.venv/\n"
                "node_modules/\ndist/\nbuild/\n*.log\n"
                "rolax1212.log\n.rolax1212/\n"
            )
            ok(".gitignore créé")
        return True
    else:
        err(f"Erreur git init : {err_msg}")
        return False


# ============================================================
#  STATUS
# ============================================================
def statut(path):
    """Retourne les fichiers modifiés/ajoutés."""
    code, out, _ = _run(["git", "status", "--short"], path)
    if code != 0 or not out:
        return []
    lignes = []
    for ligne in out.splitlines():
        if ligne.strip():
            statut_code = ligne[:2].strip()
            fichier     = ligne[3:].strip()
            lignes.append({"statut": statut_code, "fichier": fichier})
    return lignes


def afficher_statut(path):
    """Affiche le statut git dans le terminal."""
    if not est_repo_git(path):
        warn("Pas de repo Git. Tape 'git init' pour initialiser.")
        return

    fichiers = statut(path)
    if not fichiers:
        ok("Rien à committer — working tree clean")
        return

    console.print(f"\n[bold cyan]Fichiers modifiés ({len(fichiers)}) :[/bold cyan]")
    for f in fichiers:
        couleur = "green" if f["statut"] in ["A", "?"] else "yellow" if f["statut"] == "M" else "red"
        console.print(f"  [{couleur}]{f['statut']}[/{couleur}]  {f['fichier']}")
    console.print()


# ============================================================
#  COMMIT AUTOMATIQUE
# ============================================================
def commit_auto(path, modele, fichiers_projet, historique):
    """
    Génère un message de commit intelligent via le LLM
    et effectue le commit automatiquement.
    """
    path = Path(path)

    if not git_disponible():
        err("Git non installé.")
        return False

    if not est_repo_git(path):
        if confirmer("Pas de repo Git. Initialiser maintenant ?"):
            init_git(path)
        else:
            return False

    modifies = statut(path)
    if not modifies:
        ok("Rien à committer.")
        return True

    # Affiche ce qui va être commité
    afficher_statut(path)

    # Génère le message de commit via LLM
    info("Génération du message de commit...")
    noms_fichiers = ", ".join(f["fichier"] for f in modifies[:10])

    prompt = (
        f"Génère un message de commit Git court et précis (max 72 caractères) "
        f"en français pour ces fichiers modifiés : {noms_fichiers}\n\n"
        f"Format : type(scope): description\n"
        f"Types : feat, fix, refactor, style, docs, chore\n"
        f"Exemples :\n"
        f"  feat(auth): ajouter login et register\n"
        f"  fix(models): corriger relation FK Commande\n"
        f"  style(css): couleurs togolaises navbar\n\n"
        f"Réponds UNIQUEMENT avec le message de commit, rien d'autre."
    )

    historique_temp = historique + [{"role": "user", "content": prompt}]
    message = demander(historique_temp, modele, stream=False, timeout=60)

    if not message:
        message = f"chore: mise à jour {len(modifies)} fichier(s)"

    # Nettoie le message (supprime les guillemets si le LLM en ajoute)
    message = message.strip().strip('"').strip("'").splitlines()[0].strip()

    console.print(f"\n[bold yellow]Message de commit :[/bold yellow] {message}")

    if not confirmer("Effectuer ce commit ?", defaut=True):
        warn("Commit annulé.")
        return False

    # git add .
    code, _, err_msg = _run(["git", "add", "."], path)
    if code != 0:
        err(f"git add échoué : {err_msg}")
        return False

    # git commit
    code, out, err_msg = _run(["git", "commit", "-m", message], path)
    if code == 0:
        ok(f"Commit effectué : {message}")
        return True
    else:
        err(f"git commit échoué : {err_msg}")
        return False


def commit_message_libre(path, message):
    """Commit avec un message fourni directement."""
    path = Path(path)

    if not est_repo_git(path):
        err("Pas de repo Git.")
        return False

    _run(["git", "add", "."], path)
    code, out, err_msg = _run(["git", "commit", "-m", message], path)
    if code == 0:
        ok(f"Commit : {message}")
        return True
    else:
        err(f"Erreur : {err_msg}")
        return False


# ============================================================
#  HISTORIQUE
# ============================================================
def historique_git(path, nb=10):
    """Affiche les derniers commits."""
    code, out, _ = _run(
        ["git", "log", f"--max-count={nb}", "--oneline", "--decorate"],
        path
    )
    if code != 0 or not out:
        warn("Aucun commit trouvé.")
        return

    console.print(f"\n[bold cyan]Derniers {nb} commits :[/bold cyan]")
    for ligne in out.splitlines():
        console.print(f"  [dim]{ligne}[/dim]")
    console.print()


# ============================================================
#  PUSH
# ============================================================
def push(path):
    """Push vers le remote origin."""
    code, out, err_msg = _run(["git", "push"], path)
    if code == 0:
        ok("Push effectué")
    else:
        warn(f"Push échoué : {err_msg[:200]}")
        warn("Configure d'abord : git remote add origin [url]")
