"""Check custom dialogs use the shared center_window/create_dialog_window path.
Run from project root: python tools/dialog_centering_check.py --write-report
"""
from __future__ import annotations

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

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

ALLOWED_POSITIONED_POPUPS = {
    "show_language_popup",
    "show_more_popup",
}


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


def _function_name_before(text: str, pos: int) -> str:
    prefix = text[:pos]
    matches = list(re.finditer(r"^\s*def\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(", prefix, re.M))
    return matches[-1].group(1) if matches else "<module>"


def build_report() -> dict:
    issues = []
    checked = []
    for path in [ROOT / "app.py", *sorted((ROOT / "pages").glob("*.py"))]:
        if not path.exists():
            continue
        text = path.read_text(encoding="utf-8", errors="ignore")
        for match in re.finditer(r"tk\.Toplevel\(", text):
            func = _function_name_before(text, match.start())
            # Inspect the function body-ish area after Toplevel creation.  The
            # check is intentionally text-based and conservative.
            snippet = text[match.start(): match.start() + 1200]
            rel = str(path.relative_to(ROOT))
            checked.append({"file": rel, "function": func})
            if func in ALLOWED_POSITIONED_POPUPS or "overrideredirect(True)" in snippet:
                continue
            if "center_window(" not in snippet and "create_dialog_window(" not in snippet and "_center_dialog(" not in snippet and "_center_popup(" not in snippet:
                issues.append(f"{rel}:{func} creates a Toplevel without center_window/create_dialog_window")
            if "winfo_x() + max" in snippet or "winfo_y() + max" in snippet:
                issues.append(f"{rel}:{func} still uses manual winfo_x/winfo_y centering")
    return {
        "time": datetime.now().isoformat(timespec="seconds"),
        "version": _version(),
        "status": "OK" if not issues else "FAILED",
        "checked_count": len(checked),
        "checked": checked,
        "issues": issues,
    }


def main() -> int:
    write_report = "--write-report" in sys.argv
    report = build_report()
    if write_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("Dialog centering:", report["status"], f"checked={report['checked_count']}")
    for issue in report.get("issues", [])[:20]:
        print("-", issue)
    return 0 if report["status"] == "OK" else 1


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