"""PC-01: per-request middleware overhead pin.

`MgfRequestIdMiddleware` and `MgfContextMiddleware` both touch
every Django request. Per request:

`MgfRequestIdMiddleware`:
  1. `request.META.get("HTTP_X_REQUEST_ID")` — dict get.
  2. `_generate_request_id()` if absent — UUID4 allocation.
  3. `request.mgf_request_id = ...` — attribute set.
  4. `_REQUEST_ID_VAR.set(...)` — contextvar set.
  5. `self.get_response(request)` — view.
  6. `_REQUEST_ID_VAR.reset(token)` — contextvar reset.
  7. `response[REQUEST_ID_HEADER] = ...` — header set.

`MgfContextMiddleware`:
  1. `current_context()` — contextvar read + dict lookup.
  2. `request.mgf_context = ctx` — attribute set.
  3. `self.get_response(request)` — view.

For a Django app at 100 req/s per worker, a 50 µs overhead per
middleware is a 0.5 % throughput tax; at 1000 req/s, it's 1 %.
Pinning the overhead catches regressions that would grow that
tax silently.

The view (`get_response`) is stubbed to a no-op returning a bare
`HttpResponse`, so the measurement isolates the middleware code
from view-side work.

Local baseline (Linux 6.17, Python 3.11, v0.2.0):
  - MgfRequestIdMiddleware: ~6 µs/request (net).
  - MgfContextMiddleware:   ~3 µs/request (net).

Budget: 50 µs/request — ~8-15x cushion. Catches order-of-magnitude
regressions, not creep.

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

from __future__ import annotations

import time

import pytest

# Per-request middleware budget. Both middleware classes share
# the same budget — they are both expected to be sub-10 µs in
# the happy path; 50 µs is the regression-detection threshold
# (matches the tracker's 0.5 % throughput-tax framing at 100 req/s).
_PER_REQUEST_BUDGET_US = 50.0


@pytest.mark.perf
class TestMiddlewareOverhead:
    """Pin the per-request overhead of the two middleware classes."""

    def test_request_id_middleware_under_budget(self) -> None:
        from django.http import HttpResponse
        from django.test import RequestFactory

        from mgf.django._middleware import MgfRequestIdMiddleware

        rf = RequestFactory()

        def get_response(_request: object) -> HttpResponse:
            return HttpResponse("ok")

        middleware = MgfRequestIdMiddleware(get_response)

        # Build the request once and reuse — the middleware reads
        # only `request.META.get(...)` so reuse is safe + isolates
        # the measurement from RequestFactory's per-call cost.
        request = rf.get("/")

        # Warm-up.
        for _ in range(200):
            middleware(request)

        n = 5000
        start = time.perf_counter()
        for _ in range(n):
            middleware(request)
        elapsed = time.perf_counter() - start
        per_call_us = (elapsed / n) * 1_000_000

        assert per_call_us < _PER_REQUEST_BUDGET_US, (
            f"PC-01: MgfRequestIdMiddleware budget breach: "
            f"{per_call_us:.2f} µs/request (budget "
            f"{_PER_REQUEST_BUDGET_US:.0f} µs). Investigate "
            f"src/mgf/django/_middleware.py::MgfRequestIdMiddleware.__call__."
        )

    def test_context_middleware_under_budget(self) -> None:
        from django.http import HttpResponse
        from django.test import RequestFactory

        from mgf.django._middleware import MgfContextMiddleware

        rf = RequestFactory()

        def get_response(_request: object) -> HttpResponse:
            return HttpResponse("ok")

        middleware = MgfContextMiddleware(get_response)
        request = rf.get("/")

        for _ in range(200):
            middleware(request)

        n = 5000
        start = time.perf_counter()
        for _ in range(n):
            middleware(request)
        elapsed = time.perf_counter() - start
        per_call_us = (elapsed / n) * 1_000_000

        assert per_call_us < _PER_REQUEST_BUDGET_US, (
            f"PC-01: MgfContextMiddleware budget breach: "
            f"{per_call_us:.2f} µs/request (budget "
            f"{_PER_REQUEST_BUDGET_US:.0f} µs). Investigate "
            f"src/mgf/django/_middleware.py::MgfContextMiddleware.__call__."
        )
