"""AP-10 / DOC-08 pins for ``PUBLIC_API.json`` + ``PUBLIC_API.md``.

The JSON is the machine-readable companion to ``PUBLIC_API.md``;
consumer CI scripts grep/parse it to verify their pinned imports
survive an upgrade. Drift between the generator, the checked-in JSON,
and the human doc would silently invalidate those scripts — these
pins catch it.

When a test here fails:
    1. Run ``uv run python tools/generate_public_api_json.py`` to
       regenerate ``PUBLIC_API.json``.
    2. Add the new name(s) to ``PUBLIC_API.md`` with a tier +
       since-version + one-line description.
    3. Commit both in the same change as the ``__all__`` edit (DOC-08).
"""

from __future__ import annotations

import json
from pathlib import Path

from tools.generate_public_api_json import build_payload, render_json

_REPO_ROOT = Path(__file__).resolve().parent.parent.parent
_JSON_PATH = _REPO_ROOT / "PUBLIC_API.json"
_MD_PATH = _REPO_ROOT / "PUBLIC_API.md"


def test_public_api_json_exists() -> None:
    assert _JSON_PATH.exists(), (
        f"PUBLIC_API.json missing at {_JSON_PATH}. "
        f"Run `uv run python tools/generate_public_api_json.py`."
    )


def test_public_api_md_exists() -> None:
    assert _MD_PATH.exists(), f"PUBLIC_API.md missing at {_MD_PATH}."


def test_public_api_json_matches_generator_output() -> None:
    """Pin: regenerating the JSON MUST reproduce the file on disk."""
    actual = _JSON_PATH.read_text(encoding="utf-8")
    assert actual == render_json(), (
        "PUBLIC_API.json is out of sync with the live __all__ of the "
        "public modules. Regenerate with "
        "`uv run python tools/generate_public_api_json.py` and commit."
    )


def test_public_api_json_total_matches_listed_names() -> None:
    payload = json.loads(_JSON_PATH.read_text(encoding="utf-8"))
    listed = sum(len(names) for names in payload["modules"].values())
    assert listed == payload["__generated_total_names"]


def test_public_api_md_mentions_every_public_name() -> None:
    """DOC-08: PUBLIC_API.md MUST mention every name in __all__."""
    md_text = _MD_PATH.read_text(encoding="utf-8")
    payload = build_payload()
    missing = sorted(
        {name for names in payload["modules"].values() for name in names if name not in md_text}
    )
    assert not missing, (
        f"PUBLIC_API.md does not mention these public names: {missing}. "
        f"Document them (tier + since-version + description)."
    )


def test_public_api_json_version_matches_pyproject() -> None:
    payload = json.loads(_JSON_PATH.read_text(encoding="utf-8"))
    pyproject = (_REPO_ROOT / "pyproject.toml").read_text(encoding="utf-8")
    assert f'version = "{payload["__version__"]}"' in pyproject
