"""TP28 partie 5 : calcul approché des métriques DORA à partir d'un dépôt GitOps.

Conventions (à adapter et à justifier dans votre rendu) :
  - un DÉPLOIEMENT en production = un commit sur main qui modifie envs/prod/ ;
  - un ÉCHEC = un déploiement suivi d'un commit « revert » (ou « rollback ») sur envs/prod/ ;
  - la RESTAURATION = le temps entre le déploiement en échec et le commit qui le corrige.

Usage : python3 dora.py <chemin-du-dépôt-gitops> [nombre-de-jours]
"""
import subprocess
import sys
from datetime import datetime, timedelta, timezone


def git_log(repo, path):
    """Renvoie la liste (date, sha, message) des commits qui touchent path, du plus ancien au plus récent."""
    out = subprocess.run(
        ["git", "-C", repo, "log", "main", "--reverse", "--format=%cI%x09%H%x09%s", "--", path],
        check=True, capture_output=True, text=True,
    ).stdout
    commits = []
    for line in out.splitlines():
        date, sha, msg = line.split("\t", 2)
        commits.append((datetime.fromisoformat(date), sha, msg))
    return commits


def main():
    repo = sys.argv[1] if len(sys.argv) > 1 else "."
    days = int(sys.argv[2]) if len(sys.argv) > 2 else 30
    since = datetime.now(timezone.utc) - timedelta(days=days)

    deployments = [c for c in git_log(repo, "envs/prod") if c[0] >= since]
    print(f"Période : {days} jours, {len(deployments)} déploiement(s) en production")

    # 1. Deployment Frequency
    frequency = len(deployments) / days
    print(f"Deployment Frequency : {frequency:.2f} déploiement(s) par jour")

    # 2. Change Failure Rate et 3. Time to Restore
    failures, restore_times = 0, []
    for i, (date, sha, msg) in enumerate(deployments):
        nxt = deployments[i + 1] if i + 1 < len(deployments) else None
        if nxt and any(word in nxt[2].lower() for word in ("revert", "rollback")):
            failures += 1
            restore_times.append(nxt[0] - date)
    cfr = failures / len(deployments) * 100 if deployments else 0
    print(f"Change Failure Rate  : {cfr:.0f} %")
    if restore_times:
        mean = sum(restore_times, timedelta()) / len(restore_times)
        print(f"Time to Restore      : {mean} en moyenne")

    # 4. Lead Time for Changes
    # TODO : pour chaque déploiement, retrouver le commit APPLICATIF correspondant (tag d'image présent dans
    #        le message ou dans le diff de envs/prod/), puis calculer « date du déploiement − date du commit
    #        applicatif » dans le dépôt de l'application. Afficher la médiane.
    print("Lead Time for Changes : TODO")


if __name__ == "__main__":
    main()
