"""Verify the :class:`SessionVerifier` Protocol's structural contract.

The Protocol is what the FastAPI session dependency calls. These tests
pin it so adding a new method (or changing a signature) trips the
suite, forcing a deliberate update to consumers (the production
:class:`ClerkSessionVerifier` and the test :class:`MockSessionVerifier`).

We compare against ``inspect.Signature.parameters`` rather than
``get_type_hints`` because the Protocol uses forward references under
``TYPE_CHECKING`` (the standard pattern for Protocols whose return
types live in another module's domain layer).
"""

from __future__ import annotations

import inspect

from mgf.auth import MockSessionVerifier, SessionVerifier


def test_protocol_advertises_one_method() -> None:
    methods = {
        name
        for name, _ in inspect.getmembers(SessionVerifier, predicate=inspect.isfunction)
        if not name.startswith("_")
    }
    assert methods == {"verify_session"}


def test_mock_satisfies_protocol_at_runtime() -> None:
    # ``@runtime_checkable`` makes ``isinstance`` work for Protocols
    # whose member set is method-only.
    verifier: SessionVerifier = MockSessionVerifier()
    assert isinstance(verifier, SessionVerifier)


def test_verify_session_parameters() -> None:
    sig = inspect.signature(SessionVerifier.verify_session)
    params = sig.parameters
    assert list(params) == ["self", "token"]
    assert params["token"].annotation == "str"
    assert sig.return_annotation == "P_co"
