"""Guard against user-facing PUID exposure.

Internal PUID/workspace IDs are still stored for server sync and diagnostics,
but normal UI must not ask users to add friends by PUID or display PUID values.
Run from project root: python tools/puid_privacy_check.py --write-report
"""
from __future__ import annotations

import argparse
import json
import re
from datetime import datetime
from pathlib import Path
from typing import Any

ROOT = Path(__file__).resolve().parent.parent
REPORT_PATH = ROOT / "data" / "puid_privacy_latest.json"
LANG_DIR = ROOT / "lang"


def _flatten(payload: dict[str, Any], prefix: str = "") -> dict[str, str]:
    out: dict[str, str] = {}
    for key, value in payload.items():
        name = f"{prefix}.{key}" if prefix else key
        if isinstance(value, str):
            out[name] = value
        elif isinstance(value, dict):
            out.update(_flatten(value, name))
    return out


def build_report() -> dict[str, Any]:
    problems: list[dict[str, str]] = []
    checked_values = 0
    for path in sorted(LANG_DIR.glob("*.json")):
        payload = json.loads(path.read_text(encoding="utf-8"))
        for key, value in _flatten(payload).items():
            checked_values += 1
            if re.search(r"\bPUID\b|workspace[_\s-]?puid|personal[_\s-]?puid|enterprise[_\s-]?puid", value, flags=re.I):
                problems.append({"file": str(path.relative_to(ROOT)), "key": key, "value": value})

    source_expectations = {
        "pages/chat_page.py": [
            ("friend.get(\"puid\"", "Chat contact list must not display stored PUIDs."),
            ("chat_add_friend_puid", "Add Friend dialog must not ask for PUID."),
        ],
        "pages/home_page.py": [
            ("home_mode_stat_puid", "Home mode card must not expose PUID."),
            ("current_puid", "Home mode card must not read the user PUID for display."),
            ("current_workspace_puid", "Home mode card must not read workspace PUID for display."),
        ],
        "app.py": [
            ('row("profile_puid"', "Profile dialog must not display account PUID."),
            ('row("profile_workspace_puid"', "Profile dialog must not display workspace PUID."),
            ("self.t('profile_puid')", "Copied contact card must not include PUID."),
        ],
        "pages/enterprise_page.py": [
            ("customer_puid[-8:]", "Ticket rows must not display customer PUID fragments."),
        ],
    }
    for rel, checks in source_expectations.items():
        path = ROOT / rel
        if not path.exists():
            problems.append({"file": rel, "key": "missing", "value": "Required source file missing."})
            continue
        text = path.read_text(encoding="utf-8", errors="ignore")
        for marker, message in checks:
            if marker in text:
                problems.append({"file": rel, "key": marker, "value": message})

    return {
        "checked_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "checked_language_values": checked_values,
        "status": "OK" if not problems else "FAILED",
        "problems": problems,
        "notes": [
            "PUID remains available internally for server sync, CRM linking, and diagnostics.",
            "User-facing friend discovery must use QR code, phone, email, account, or public friend code.",
        ],
    }


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--write-report", action="store_true")
    args = parser.parse_args()
    report = build_report()
    print("NexaOffice PUID Privacy Check")
    print(f"- Checked language values: {report['checked_language_values']}")
    print(f"- Status: {report['status']}")
    for item in report["problems"][:50]:
        print(f"  {item['file']} {item['key']}: {item['value']}")
    if args.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(f"- Report: {REPORT_PATH.relative_to(ROOT)}")
    return 0 if report["status"] == "OK" else 1


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