"""PC-03: ``bearer_session`` dependency wrapper overhead — baseline-relative.

The dependency returned by ``bearer_session()`` runs per protected endpoint:

  1. `_extract_bearer_token(request, cookie_name)` — header read + scheme
     parse, optional cookie fallback. ~2-5 µs.
  2. `getattr(request.app.state, verifier_attr, None)` — ~1 µs.
  3. `await verifier.verify_session(token)` — THE COST. The verifier itself
     dominates (in-memory ~10 µs, JWT ~50 µs, IdP 50-500 ms) — but the
     verifier's cost is **consumer-side** and NOT what this pin measures.

This test isolates the **wrapper overhead** by mocking ``verify_session`` as a
no-op coroutine returning a fixed principal. What's left is exactly what
mgf-fastapi owns: token extraction + verifier lookup + the dependency-shape
glue around the call. Compared to the recorded baseline (PF-01/07) — NOT the
old absolute 20 µs budget.

Marker: ``perf`` (registered in pyproject.toml). Excluded from the default
suite; run via ``pytest -m perf``.
"""

from __future__ import annotations

import asyncio
import time
from typing import TYPE_CHECKING, Any

import pytest
from fastapi import FastAPI
from starlette.requests import Request

from mgf.fastapi.security import bearer_session

if TYPE_CHECKING:
    from tests.perf.conftest import Baselines

pytestmark = pytest.mark.perf


class _NoOpVerifier:
    """Fast no-op verifier — returns immediately with a fixed principal.

    The principal value is irrelevant; the test only measures the wrapper cost
    on the happy path.
    """

    async def verify_session(self, token: str) -> dict[str, Any]:
        return {"user": "perf-test"}


def _make_request_with_bearer(app: FastAPI) -> Request:
    """Build a synthetic Request with a valid Bearer header."""
    scope: dict[str, Any] = {
        "type": "http",
        "app": app,
        "headers": [(b"authorization", b"Bearer perf-test-token-abcdef")],
    }
    return Request(scope)


def test_wrapper_no_regression(baselines: Baselines) -> None:
    app = FastAPI()
    app.state.auth_provider = _NoOpVerifier()
    dep = bearer_session()
    request = _make_request_with_bearer(app)

    async def _drive() -> float:
        # Warm-up — first call pays cache costs.
        for _ in range(200):
            await dep(request)

        n = 10_000
        start = time.perf_counter()
        for _ in range(n):
            await dep(request)
        elapsed = time.perf_counter() - start
        return (elapsed / n) * 1_000_000

    per_call_us = asyncio.run(_drive())
    baselines.assert_no_regression(
        "bearer_session_wrapper_p50_us",
        per_call_us,
        units="us",
        description="bearer_session dependency wrapper overhead (verifier mocked), mean over 10k",
    )
