"""Pin: ``PUBLIC_API.md`` MUST list every public name in ``__all__``.

Rule **AP-10** (mirrored from `mgf-common`'s API-design standard) —
the public-API document is the contract list. It MUST stay in sync
with ``__all__`` of every public module, OR the contract drifts: a
public name nobody documented becomes "you should not have depended
on that".

The check is deliberately substring-based against the
``PUBLIC_API.md`` text rather than a structured parser — it
tolerates wording changes around the name (signature shape, type
hints, prose) but fails loudly if a name disappears from the doc
entirely.
"""

from __future__ import annotations

from pathlib import Path

import pytest

import mgf.apiprobe
import mgf.apiprobe.auth
import mgf.apiprobe.checks
import mgf.apiprobe.cli
import mgf.apiprobe.config
import mgf.apiprobe.core
import mgf.apiprobe.core.matchers
import mgf.apiprobe.exceptions
import mgf.apiprobe.factories
import mgf.apiprobe.reporting
import mgf.apiprobe.schema
import mgf.apiprobe.transport

PUBLIC_API_PATH = Path(__file__).resolve().parent.parent.parent / "PUBLIC_API.md"


def _public_names() -> list[tuple[str, str]]:
    """Yield every (module_label, name) for the project's public surface."""
    out: list[tuple[str, str]] = []
    for module in (
        mgf.apiprobe,
        mgf.apiprobe.exceptions,
        mgf.apiprobe.config,
        mgf.apiprobe.core,
        mgf.apiprobe.core.matchers,
        mgf.apiprobe.auth,
        mgf.apiprobe.checks,
        mgf.apiprobe.factories,
        mgf.apiprobe.schema,
        mgf.apiprobe.transport,
        mgf.apiprobe.reporting,
        mgf.apiprobe.cli,
    ):
        for name in module.__all__:
            out.append((module.__name__, name))
    return out


@pytest.mark.parametrize("module_label,name", _public_names())
def test_public_name_appears_in_public_api_doc(module_label: str, name: str) -> None:
    """Every name in ``__all__`` MUST appear in PUBLIC_API.md."""
    text = PUBLIC_API_PATH.read_text()
    # The doc renders names in backticks (e.g., `Probe(...)` or bare
    # `BearerAuth`). Match on the bare name with backtick prefix so
    # we don't false-positive on prose that happens to contain the
    # word.
    needle = f"`{name}"
    assert needle in text, (
        f"AP-10: {module_label}.{name!r} is in __all__ but does not "
        f"appear in PUBLIC_API.md. Add a row in the section for "
        f"{module_label!r} with stability tier + one-line description, "
        f"or remove the name from __all__."
    )


def test_public_api_doc_exists_and_is_non_empty() -> None:
    """Sanity: the doc exists and has content."""
    assert PUBLIC_API_PATH.exists(), f"AP-10: PUBLIC_API.md missing at {PUBLIC_API_PATH}"
    assert PUBLIC_API_PATH.stat().st_size > 1000, (
        f"AP-10: PUBLIC_API.md exists but is suspiciously small "
        f"({PUBLIC_API_PATH.stat().st_size} bytes)"
    )
