"""Check that the release source package stays clean and overwrite-friendly.

This prevents the project from accumulating one-off release notes, legacy schema
snapshots, build artifacts, and cache folders after many fast iterations.
"""
from __future__ import annotations

import json
import re
from datetime import datetime
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
REPORT_PATH = ROOT / "data" / "package_cleanliness_latest.json"

ALLOWED_DOCS = {
    "README_CN.md",
    "OVERWRITE_INSTALL_CN.md",
    "BUILD_EXE_README_CN.md",
    "SERVER_DEPLOYMENT_CN.md",
    "TROUBLESHOOTING_CN.md",
    "QA_SELF_CHECK_CN.md",
    "CLEAN_PACKAGE_MANIFEST_CN.md",
    "RELEASE_v2026.06.20.28_CN.md",
    "TEN_VERSION_MILESTONE_20260620_30_CN.md",
    "TEN_VERSION_MILESTONE_20260620_40_CN.md",
    "TEN_VERSION_MILESTONE_20260620_50_CN.md",
    "TEN_VERSION_MILESTONE_20260620_60_CN.md",
    "TEN_VERSION_MILESTONE_20260620_70_CN.md",
    "TEN_VERSION_MILESTONE_20260620_80_CN.md",
    "TEN_VERSION_MILESTONE_20260620_90_CN.md",
    "TEN_VERSION_MILESTONE_20260620_100_CN.md",
    "TEN_VERSION_MILESTONE_20260621_10_CN.md",
    "TEN_VERSION_MILESTONE_20260621_20_CN.md",
    "UPDATE_HISTORY_CN.md",
    "UPDATE_HISTORY_EN.md",
    "UPDATE_HISTORY_ID.md",
}

ROOT_DOC_PATTERNS = [
    re.compile(r"^VERSION_\d.*\.(txt|md)$", re.I),
    re.compile(r"^ANTIVIRUS_.*\.(txt|md)$", re.I),
    re.compile(r"^PORTABLE_.*\.(txt|md)$", re.I),
]

OLD_DOC_PATTERNS = [
    re.compile(r"^VERSION_.*\.(txt|md)$", re.I),
    re.compile(r"^.*_202606\d+_.*\.(txt|md)$", re.I),
    re.compile(r"^.*_V\d+_.*\.(txt|md)$", re.I),
]


def _version() -> str:
    text = (ROOT / "core" / "constants.py").read_text(encoding="utf-8", errors="ignore")
    match = re.search(r'APP_VERSION\s*=\s*"([^"]+)"', text)
    return match.group(1) if match else "unknown"


def build_report() -> dict:
    issues: list[str] = []
    docs_dir = ROOT / "docs"
    docs = sorted(p.name for p in docs_dir.glob("*") if p.is_file()) if docs_dir.exists() else []

    extra_docs = sorted(set(docs) - ALLOWED_DOCS)
    missing_docs = sorted(ALLOWED_DOCS - set(docs))
    if extra_docs:
        issues.append("docs contains non-curated files: " + ", ".join(extra_docs[:20]))
    if missing_docs:
        issues.append("docs missing curated files: " + ", ".join(missing_docs[:20]))

    for name in docs:
        for pat in OLD_DOC_PATTERNS:
            if pat.match(name) and name not in ALLOWED_DOCS:
                issues.append(f"old one-off doc remains: docs/{name}")
                break

    for p in ROOT.iterdir():
        if not p.is_file():
            continue
        for pat in ROOT_DOC_PATTERNS:
            if pat.match(p.name):
                issues.append(f"root duplicate/temporary doc remains: {p.name}")
                break

    schema_files = sorted(p.name for p in (ROOT / "data").glob("server_schema*.json"))
    if schema_files != ["server_schema_latest.json"]:
        issues.append("legacy server schema snapshots remain: " + ", ".join(schema_files[:30]))

    for forbidden in ["build", "dist"]:
        for p in ROOT.rglob(forbidden):
            if p.exists():
                issues.append(f"build/cache artifact remains: {p.relative_to(ROOT)}")
                break

    report = {
        "time": datetime.now().isoformat(timespec="seconds"),
        "version": _version(),
        "status": "OK" if not issues else "FAILED",
        "doc_count": len(docs),
        "docs": docs,
        "schema_files": schema_files,
        "issues": issues,
    }
    return report


def main() -> int:
    report = build_report()
    REPORT_PATH.parent.mkdir(parents=True, exist_ok=True)
    REPORT_PATH.write_text(json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8")
    print("Package cleanliness:", report["status"], f"docs={report['doc_count']}")
    if report["issues"]:
        for issue in report["issues"][:20]:
            print("-", issue)
    return 0 if report["status"] == "OK" else 1


if __name__ == "__main__":
    raise SystemExit(main())
