#!/usr/bin/env python3
"""Régénère la feuille « L4.7 » du classeur de contre-recette DEPUIS le cahier.

Convention du 11/08 (Enguerran) reprise ici : le `.md` fait foi, le reste est une
vue. Les scénarios ne sont donc jamais retapés dans Excel — ils sont extraits des
tableaux du cahier. Un scénario ajouté au cahier apparaît dans le classeur à la
prochaine exécution ; les deux ne peuvent pas diverger.

Usage : python3 scripts/contre_recette_l47.py
Dépendance : openpyxl.
"""
import copy
import re

import openpyxl
from openpyxl.styles import Alignment, Font, PatternFill

CAHIER = "docs/roadmap/recette/RECETTE_L47_REFONTE_UX.md"
CLASSEUR = "docs/roadmap/recette/CONTRE_RECETTE_L0_L4.xlsx"
LARGEURS = {"A": 34.0, "B": 62.0, "C": 16.0, "D": 14.0, "E": 40.0}


def sans_markdown(texte: str) -> str:
    """Le gras et le code se lisent mal dans une cellule Excel."""
    texte = re.sub(r"\*\*(.+?)\*\*", r"\1", texte)
    return texte.replace("`", "")


def extraire_sections(chemin: str) -> list[dict]:
    sections: list[dict] = []
    courante = None

    for ligne in open(chemin, encoding="utf-8"):
        entete = re.match(r"^## (S\d+) — (.+)$", ligne.strip())
        if entete:
            courante = {"titre": f"{entete.group(1)} · {sans_markdown(entete.group(2))}", "lignes": []}
            sections.append(courante)
            continue

        if courante is None or not ligne.startswith("| S"):
            continue

        cellules = [c.strip() for c in ligne.strip().strip("|").split("|")]
        if len(cellules) >= 3 and re.match(r"^S\d+\.\d+$", cellules[0]):
            courante["lignes"].append(
                (cellules[0], f"{sans_markdown(cellules[1])} → {sans_markdown(cellules[2])}")
            )

    return [s for s in sections if s["lignes"]]


def main() -> None:
    sections = extraire_sections(CAHIER)
    total = sum(len(s["lignes"]) for s in sections)

    classeur = openpyxl.load_workbook(CLASSEUR)
    modele = classeur["L4"]

    if "L4.7" in classeur.sheetnames:
        del classeur["L4.7"]
    feuille = classeur.create_sheet("L4.7")

    for colonne, largeur in LARGEURS.items():
        feuille.column_dimensions[colonne].width = largeur

    feuille["A1"] = (
        "Contre-recette L4.7 — refonte UX/UI, écrans v3 — un testeur par ligne de scénario"
    )
    feuille["A1"].font = copy.copy(modele["A1"].font)

    entetes = [
        "Réf / Scénario",
        "Description (voir RECETTE_L47_REFONTE_UX.docx)",
        "Testeur",
        "Verdict (OK / KO)",
        "Commentaire / capture",
    ]
    for i, texte in enumerate(entetes, 1):
        cellule = feuille.cell(row=2, column=i, value=texte)
        gabarit = modele.cell(row=2, column=i)
        cellule.font = copy.copy(gabarit.font)
        cellule.fill = copy.copy(gabarit.fill)
        cellule.alignment = copy.copy(gabarit.alignment)

    gras = Font(bold=True)
    fond_section = PatternFill("solid", fgColor="00EFEAE1")
    retour = Alignment(wrap_text=True, vertical="top")

    rang = 3
    for section in sections:
        titre = feuille.cell(row=rang, column=1, value=section["titre"])
        titre.font, titre.alignment = gras, retour
        for colonne in range(1, 6):
            feuille.cell(row=rang, column=colonne).fill = fond_section
        rang += 1

        for reference, description in section["lignes"]:
            feuille.cell(row=rang, column=1, value=reference).alignment = retour
            feuille.cell(row=rang, column=2, value=description).alignment = retour
            for colonne in (3, 4, 5):
                feuille.cell(row=rang, column=colonne).alignment = retour
            rang += 1

    feuille.freeze_panes = "A3"

    mode = classeur["Mode d'emploi"]
    mode["A1"] = "Contre-recette utilisateurs — L0 à L4, puis L4.7 (refonte UX/UI)"
    mode["A8"] = (
        "6. Feuille L4.7 : les écarts ASSUMÉS avec les maquettes sont listés au §7 du cahier. "
        "Un écran qui diffère de la maquette n'est pas un KO — vérifier le §7 avant d'ouvrir une issue."
    )

    classeur.save(CLASSEUR)
    print(f"Feuille L4.7 régénérée : {len(sections)} sections, {total} scénarios.")


if __name__ == "__main__":
    main()
