#!/usr/bin/env python3
"""Check that all public SDK exports are mentioned in the documentation.

Run from ``packages/memory-sdk/``::

    python scripts/check_docs_coverage.py

Exits with code 1 when coverage drops below 95 %.
"""

from __future__ import annotations

import importlib
import re
from pathlib import Path

# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------

MODULES_TO_CHECK: list[str] = [
    "arandu",
    "arandu.write",
    "arandu.read",
    "arandu.background",
    "arandu.db",
]

DOCS_DIR = Path("docs/en")

MIN_COVERAGE_PCT = 95.0

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------


def collect_exports(module_name: str) -> set[str]:
    """Import *module_name* and return its ``__all__`` names.

    Returns an empty set (with a warning) when the module has no ``__all__``.
    """
    try:
        mod = importlib.import_module(module_name)
    except ImportError as exc:
        print(f"  WARNING: could not import {module_name}: {exc}")
        return set()

    all_names: list[str] | None = getattr(mod, "__all__", None)
    if all_names is None:
        print(f"  WARNING: {module_name} has no __all__, skipping")
        return set()

    return set(all_names)


def load_docs_text(docs_dir: Path) -> str:
    """Concatenate the text of every ``.md`` file under *docs_dir*."""
    parts: list[str] = []
    for md_file in sorted(docs_dir.rglob("*.md")):
        parts.append(md_file.read_text(encoding="utf-8"))
    return "\n".join(parts)


def name_is_documented(name: str, docs_text: str) -> bool:
    r"""Return True if *name* appears as a whole word in *docs_text*.

    Uses a word-boundary regex so that e.g. ``MemoryClient`` matches only
    ``MemoryClient`` and not ``MemoryClientFoo``.
    """
    pattern = rf"\b{re.escape(name)}\b"
    return bool(re.search(pattern, docs_text))


# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------


def main() -> int:
    if not DOCS_DIR.is_dir():
        print(f"ERROR: docs directory not found at {DOCS_DIR.resolve()}")
        return 1

    # 1. Collect all public exports across configured modules
    print("Collecting public exports ...")
    all_exports: set[str] = set()
    for module_name in MODULES_TO_CHECK:
        names = collect_exports(module_name)
        if names:
            print(f"  {module_name}: {len(names)} exports")
            all_exports |= names

    # Exclude dunder names (e.g. __version__) — they are not user-facing API
    all_exports = {n for n in all_exports if not n.startswith("__")}

    if not all_exports:
        print("ERROR: no public exports found — is the SDK installed?")
        return 1

    # 2. Load docs text
    docs_text = load_docs_text(DOCS_DIR)
    if not docs_text.strip():
        print(f"ERROR: no documentation found in {DOCS_DIR.resolve()}")
        return 1

    # 3. Check each export
    documented: set[str] = set()
    undocumented: set[str] = set()

    for name in sorted(all_exports):
        if name_is_documented(name, docs_text):
            documented.add(name)
        else:
            undocumented.add(name)

    total = len(all_exports)
    pct = (len(documented) / total) * 100 if total else 0.0

    # 4. Report
    print()
    print("=" * 60)
    print("  SDK Docs Coverage Report")
    print("=" * 60)
    print(f"  Total public exports:  {total}")
    print(f"  Documented:            {len(documented)}")
    print(f"  Undocumented:          {len(undocumented)}")
    print(f"  Coverage:              {pct:.1f}%")
    print(f"  Threshold:             {MIN_COVERAGE_PCT:.1f}%")
    print("=" * 60)

    if undocumented:
        print()
        print("Undocumented exports:")
        for name in sorted(undocumented):
            print(f"  - {name}")

    if pct < MIN_COVERAGE_PCT:
        print()
        print(f"FAIL: coverage {pct:.1f}% is below the {MIN_COVERAGE_PCT:.1f}% threshold.")
        return 1

    print()
    print("PASS: docs coverage is above threshold.")
    return 0


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