﻿#!/usr/bin/env python3
"""Regenerate RULEFOLDER/CHANGELOG.md from RULEFOLDER/changes/*.md.

CHANGELOG.md is a build artifact. Never edit it by hand; edit the fragment.

Usage:
  python RULEFOLDER/tools/build_changelog.py            # rewrite CHANGELOG.md
  python RULEFOLDER/tools/build_changelog.py --check    # exit 1 if CHANGELOG.md is stale
  python RULEFOLDER/tools/build_changelog.py --csv out.csv   # flat export for Excel / Power BI
"""
import argparse
import csv
import sys

from _fragments import CHANGELOG, load_fragments, as_list


def render(frags):
    lines = [
        "# CHANGELOG — TikTok Manager",
        "",
        "> **Generated file.** Source of truth is `RULEFOLDER/changes/*.md` (one file per change).",
        "> Rebuild with `python RULEFOLDER/tools/build_changelog.py`. Do not edit by hand.",
        "",
        f"{len(frags)} changes. Newest last. IDs: legacy `CHG-NNN` (before 2026-09-24) "
        "and `CHG-YYYYMMDD-DEV-NN` (see `CONTRIBUTING.md`).",
        "",
        "## Index",
        "",
        "| # | ID | Date | Author | Type | Scope | Title | Security | API |",
        "|---|----|------|--------|------|-------|-------|----------|-----|",
    ]
    for i, f in enumerate(frags, 1):
        m = f["meta"]
        api = ", ".join(as_list(m.get("api_endpoints")))
        if not api:
            api = "n/a" if m.get("parity_exception") else "—"
        lines.append(
            f"| {i} | {m.get('id', '?')} | {m.get('date', '')} | {m.get('author', '')} | {m.get('type', '')} | "
            f"{', '.join(as_list(m.get('scope')))} | {m.get('title', '')} | "
            f"{m.get('security_impact', '') or '—'} | {api} |"
        )
    lines += ["", "---", ""]
    for f in frags:
        m = f["meta"]
        lines.append(f"## {m.get('id', '?')} — {m.get('title', '')}")
        lines.append(f"**Date:** {m.get('date', '')}  ")
        lines.append(f"**Author:** {m.get('author', '')}  ")
        lines.append(f"**Type:** {m.get('type', '')}  ")
        lines.append(f"**Scope:** {', '.join(as_list(m.get('scope')))}  ")
        if as_list(m.get("patterns")):
            lines.append(f"**Design Patterns:** {', '.join(as_list(m.get('patterns')))}  ")
        if as_list(m.get("files")):
            lines.append("**Files:** " + ", ".join(f"`{x}`" for x in as_list(m.get("files"))) + "  ")
        if as_list(m.get("gui_routes")):
            lines.append(f"**GUI:** {', '.join(as_list(m.get('gui_routes')))}  ")
        if as_list(m.get("api_endpoints")):
            lines.append(f"**API:** {', '.join(as_list(m.get('api_endpoints')))}  ")
        if m.get("parity_exception"):
            lines.append(f"**Parity exception:** {m.get('parity_exception')}  ")
        lines.append(f"**Security impact:** {m.get('security_impact', '') or '—'}  ")
        if m.get("breaking") is True:
            lines.append("**BREAKING CHANGE**  ")
        lines.append("")
        lines.append(f["body"].strip())
        lines += ["", "---", ""]
    return "\n".join(lines).rstrip() + "\n"


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--check", action="store_true")
    ap.add_argument("--csv")
    args = ap.parse_args()

    frags = load_fragments()
    text = render(frags)

    if args.csv:
        cols = ["id", "date", "author", "type", "scope", "title", "status", "breaking", "patterns",
                "files", "gui_routes", "api_endpoints", "parity_exception", "api_doc_updated",
                "security_impact", "tests"]
        with open(args.csv, "w", newline="", encoding="utf-8-sig") as fh:
            w = csv.writer(fh)
            w.writerow(cols)
            for f in frags:
                m = f["meta"]
                row = []
                for c in cols:
                    v = m.get(c, "")
                    row.append("; ".join(str(x) for x in v) if isinstance(v, list) else v)
                w.writerow(row)
        print("CSV written:", args.csv)

    if args.check:
        current = CHANGELOG.read_text(encoding="utf-8") if CHANGELOG.exists() else ""
        if current != text:
            print("CHANGELOG.md is stale. Run: python RULEFOLDER/tools/build_changelog.py")
            sys.exit(1)
        print("CHANGELOG.md is up to date.")
        return

    CHANGELOG.write_text(text, encoding="utf-8", newline="\n")
    print(f"CHANGELOG.md rebuilt from {len(frags)} fragments.")


if __name__ == "__main__":
    main()

