"""PC-01: ``tenant_session`` per-call Python overhead pin.

`tenant_session` runs at the start of every tenant-scoped
request:

  1. UUID parse (`UUID(tenant_id)` or `isinstance(tenant_id, UUID)`
     short-circuit) — sub-µs.
  2. `str(validated)` — sub-µs.
  3. f-string format — sub-µs.
  4. `await session.execute(text(...))` — SQL roundtrip.
     **NOT measured here** — the SQL is owned by the consumer + DB.
  5. `yield session` — context-manager yield.

Strategy: mock `session.execute` as a no-op `AsyncMock` so the
SQL roundtrip is excluded; the measurement isolates the Python-
side wrapper overhead. Cover both input shapes (str + UUID
object) since the validation path differs.

Local baseline (Linux 6.17, Python 3.11, v0.2.0):
  - str input:   ~7 µs/call
  - UUID input:  ~9 µs/call

Tracker proposed a ≤ 10 µs/call budget but local measurement
comes in at ~7-9 µs — 10-40 % cushion would be too tight for
CI noise. Budget raised to **30 µs/call** (~3.5x cushion).
A breach signals real per-call work crept in (extra
allocation, redundant UUID re-validation, etc.).

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 asyncio
import time
from unittest.mock import AsyncMock, MagicMock
from uuid import UUID

import pytest

from mgf.sqlalchemy import tenant_session

# Per-call wrapper budget. EXCLUDES the SQL roundtrip (mocked
# via AsyncMock) AND the network latency. Catches regressions
# in UUID validation, str format, or context-manager glue.
# 30 µs = ~3.5x local measurement of ~9 µs.
_PER_CALL_BUDGET_US = 30.0

_TENANT_ID_STR = "11111111-2222-3333-4444-555555555555"
_TENANT_ID_UUID = UUID(_TENANT_ID_STR)


def _make_session_mock() -> MagicMock:
    """Build a session-shaped mock with a no-op `execute` coroutine."""
    session = MagicMock()
    session.execute = AsyncMock(return_value=None)
    return session


@pytest.mark.perf
class TestTenantSessionOverhead:
    """Pin the per-call Python overhead of `tenant_session`."""

    def test_str_input_under_budget(self) -> None:
        """`tenant_session(session, '<uuid-str>')` stays under budget.

        Covers the str path: `UUID(tenant_id)` validation runs at
        the call site.
        """

        async def _drive() -> float:
            session = _make_session_mock()

            # Warm-up.
            for _ in range(200):
                async with tenant_session(session, _TENANT_ID_STR):
                    pass

            n = 10_000
            start = time.perf_counter()
            for _ in range(n):
                async with tenant_session(session, _TENANT_ID_STR):
                    pass
            elapsed = time.perf_counter() - start
            return (elapsed / n) * 1_000_000

        per_call_us = asyncio.run(_drive())

        assert per_call_us < _PER_CALL_BUDGET_US, (
            f"PC-01: tenant_session(str) budget breach: "
            f"{per_call_us:.2f} µs/call (budget "
            f"{_PER_CALL_BUDGET_US:.0f} µs). Investigate "
            f"src/mgf/sqlalchemy/_session.py::tenant_session — "
            f"likely a regression in UUID validation or f-string format."
        )

    def test_uuid_input_under_budget(self) -> None:
        """`tenant_session(session, UUID(...))` stays under budget.

        Covers the UUID-object path: validation short-circuits via
        `isinstance(tenant_id, UUID)`, so only `str(uuid)` runs.
        """

        async def _drive() -> float:
            session = _make_session_mock()

            for _ in range(200):
                async with tenant_session(session, _TENANT_ID_UUID):
                    pass

            n = 10_000
            start = time.perf_counter()
            for _ in range(n):
                async with tenant_session(session, _TENANT_ID_UUID):
                    pass
            elapsed = time.perf_counter() - start
            return (elapsed / n) * 1_000_000

        per_call_us = asyncio.run(_drive())

        assert per_call_us < _PER_CALL_BUDGET_US, (
            f"PC-01: tenant_session(UUID) budget breach: "
            f"{per_call_us:.2f} µs/call (budget "
            f"{_PER_CALL_BUDGET_US:.0f} µs). Investigate "
            f"src/mgf/sqlalchemy/_session.py::tenant_session — "
            f"likely a regression in str(UUID) or context-manager glue."
        )
