#!/usr/bin/env python3
"""Crée les issues GitHub à partir de 03_BACKLOG_ISSUES.md.

Usage :
  python3 create_github_issues.py --dry-run
  python3 create_github_issues.py --repo AAZTEKDEV/EFEKTIVACADEMIE-BACK            # tout dans un repo
  python3 create_github_issues.py --split front=AAZTEKDEV/EFEKTIVACADEMIE-FRONT \
      back=AAZTEKDEV/EFEKTIVACADEMIE-BACK pipeline=AAZTEK/microlearning-video-v2-light

Référence : EFEKTIVACADEMIE-* branche development (les clones EACLAUDE ne sont pas la référence).
Mode --repo (recommandé pour un suivi unifié) : toutes les issues dans un seul repo,
avec labels repo:front / repo:back / repo:pipeline.
Mode --split : chaque issue va dans le repo correspondant à son tag [FRONT]/[BACK]/…
(les issues [FRONT+BACK] vont dans le repo back avec label repo:front en plus).

Crée aussi les milestones « Sprint 1 » … « Sprint 10 » et les labels nécessaires.
"""
import argparse, json, re, subprocess, sys
from pathlib import Path

MD = Path(__file__).parent / "03_BACKLOG_ISSUES.md"

SPRINT_RE = re.compile(r"^## Sprint (\d+) — (.+)$")
ISSUE_RE = re.compile(r"^### (EA-\d+) · \[([A-Z+]+)\] (.+)$")
META_RE = re.compile(r"^`([^`]+)`(?: `([^`]+)`)*.*?(?:— Dépend de : (.+))?$")

LABEL_COLORS = {
    "type:feat": "1d76db", "type:fix": "d93f0b", "type:sec": "b60205",
    "type:infra": "5319e7", "type:design": "fbca04", "bloquant": "000000",
    "repo:front": "0e8a16", "repo:back": "006b75", "repo:pipeline": "c2e0c6",
}


def parse():
    issues, sprint_no, sprint_title = [], None, None
    lines = MD.read_text(encoding="utf-8").splitlines()
    i = 0
    while i < len(lines):
        line = lines[i]
        m = SPRINT_RE.match(line)
        if m:
            sprint_no, sprint_title = int(m.group(1)), m.group(2).strip()
        m = ISSUE_RE.match(line)
        if m:
            ea, repo_tag, title = m.group(1), m.group(2), m.group(3).strip()
            # ligne méta (labels + dépendances)
            meta_line = lines[i + 1] if i + 1 < len(lines) else ""
            labels = re.findall(r"`([a-z:]+)`", meta_line)
            dep_m = re.search(r"Dépend de : (.+)$", meta_line)
            deps = dep_m.group(1).strip() if dep_m else "—"
            # corps = jusqu'à la prochaine issue / section
            body_lines = []
            j = i + 2
            while j < len(lines) and not lines[j].startswith("### ") and not lines[j].startswith("## ") and lines[j] != "---":
                body_lines.append(lines[j])
                j += 1
            issues.append({
                "ea": ea, "repo_tag": repo_tag, "title": title,
                "sprint": sprint_no, "sprint_title": sprint_title,
                "labels": [l for l in labels if l in LABEL_COLORS or l.startswith("type:")],
                "deps": deps, "body": "\n".join(body_lines).strip(),
            })
            i = j
            continue
        i += 1
    return issues


def gh(args, **kw):
    return subprocess.run(["gh"] + args, check=True, capture_output=True, text=True, **kw).stdout


def ensure_meta(repo, sprints):
    existing = json.loads(gh(["api", f"repos/{repo}/milestones?state=all&per_page=100"]))
    have = {m["title"]: m["number"] for m in existing}
    nums = {}
    for s in sorted(sprints):
        title = f"Sprint {s}"
        if title in have:
            nums[s] = have[title]
        else:
            m = json.loads(gh(["api", f"repos/{repo}/milestones", "-f", f"title={title}"]))
            nums[s] = m["number"]
    for name, color in LABEL_COLORS.items():
        subprocess.run(["gh", "label", "create", name, "--repo", repo, "--color", color],
                       capture_output=True)  # ignore « already exists »
    return nums


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--dry-run", action="store_true")
    ap.add_argument("--repo")
    ap.add_argument("--split", nargs="*")
    ap.add_argument("--skip", default="", help="Réfs EA-xxx à ne pas créer (déjà existantes), séparées par des virgules")
    args = ap.parse_args()

    issues = parse()
    skip = {s.strip() for s in args.skip.split(",") if s.strip()}
    if skip:
        issues = [it for it in issues if it["ea"] not in skip]
        print(f"({len(skip)} issue(s) ignorée(s) : {', '.join(sorted(skip))})")
    print(f"{len(issues)} issues parsées.")
    for it in issues:
        print(f"  S{it['sprint']:>2} {it['ea']} [{it['repo_tag']:<14}] {it['title'][:70]} "
              f"labels={it['labels']} deps={it['deps']}")
    if args.dry_run:
        return

    split = {}
    if args.split:
        split = dict(kv.split("=", 1) for kv in args.split)
    if not args.repo and not split:
        sys.exit("--repo ou --split requis (ou --dry-run).")

    def target(it):
        if args.repo:
            return args.repo
        tag = it["repo_tag"].lower()
        if "pipeline" in tag:
            return split.get("pipeline", split["back"])
        if tag == "front":
            return split["front"]
        return split["back"]

    milestones = {}
    for repo in {target(it) for it in issues}:
        milestones[repo] = ensure_meta(repo, {it["sprint"] for it in issues})

    for it in issues:
        repo = target(it)
        labels = list(it["labels"])
        for part in it["repo_tag"].lower().split("+"):
            labels.append(f"repo:{part}")
        body = (f"**Sprint {it['sprint']}** — {it['sprint_title']}\n"
                f"**Dépend de** : {it['deps']}\n\n{it['body']}\n\n"
                f"_Backlog source : `docs/roadmap/03_BACKLOG_ISSUES.md` ({it['ea']})._")
        cmd = ["issue", "create", "--repo", repo,
               "--title", f"{it['ea']} · {it['title']}",
               "--body", body,
               "--milestone", f"Sprint {it['sprint']}"]
        for l in labels:
            cmd += ["--label", l]
        url = gh(cmd).strip()
        print(f"{it['ea']} → {url}")


if __name__ == "__main__":
    main()
