"""Performance pins for ``mgf.hrb.fmt`` — PR-* test plan T6.

The fmt helpers are called inside hot operator-facing render paths
in both the CLI (via ``mgf-hrb cli doctor``) and the Qt GUI (via
``DoctorViewModel`` populating the doctor pane on every poll
tick). If a "small refactor" accidentally introduces a per-call
allocation, regex compile, or stdlib-call into one of them, the
operator-perceived UI smoothness degrades silently.

Budgets (p99 over 50k iter after 1k warmup):

  format_uptime               < 1 µs   (current measured: ~150 ns)
  format_duration             < 1 µs   (current measured: ~140 ns)
  format_rss                  < 1 µs   (current measured: ~240 ns)
  format_severity_glyph       < 1 µs   (current measured: ~125 ns)
  import mgf.hrb.fmt cold     < 5 ms   (current measured: ~160 µs)

The 1 µs budget gives ~5x slack over current measurements for
hardware variance + future defensive code. If a helper crosses
the budget the failure message names the regression specifically
so the contributor can target the slowdown without re-running
profiling. Nightly-only via the ``perf`` marker.

**Not measurable under a tracer** (FEEDBACK ``CI-01``). These are
sub-µs per-call pins, and a line-level tracer (``coverage``, a
debugger, a profiler) fires its hook on *every line of the helper*
— which inflates these helpers 4-5x (measured in
``python:3.13-slim``: ``format_rss`` 297 ns → 1430 ns) while the
1 µs budget stays put. That is not a regression in the helper; it
is the tracer being timed. It made ``main`` red for weeks: the
``supervisor-tier-0-3`` step wraps the whole suite in ``coverage
run`` (#23c) and ``patch = ["subprocess"]`` propagates the tracer
into every supervisor worker, so these three pins failed in CI
and passed everywhere else. ``_p99_ns`` therefore skips when a
tracer is installed — see ``_tracer_active``. The pins keep their
teeth in the un-traced lanes: plain ``pytest -m perf`` and the
``nightly-tier-0-3`` step (bare ``mgf-test-supervisor``, no
``coverage run``).

The cold-import budget below deliberately does NOT take that skip:
5 ms against a ~160 µs measurement is ~30x headroom, it survives
the tracer, and it is worth keeping live in the main lane.
"""

from __future__ import annotations

import importlib
import sys
import time
from typing import TYPE_CHECKING

import pytest

if TYPE_CHECKING:
    from collections.abc import Callable

from mgf.hrb.fmt import (
    format_duration,
    format_rss,
    format_severity_glyph,
    format_uptime,
)

pytestmark = pytest.mark.perf

_WARMUP = 1_000
_MEASUREMENTS = 50_000
_BUDGET_NS = 1_000  # 1 µs per call


def _tracer_active() -> bool:
    """True when a line-level tracer is installed in this interpreter
    — ``coverage``, ``pdb``, a profiler, anything.

    Two mechanisms, because CPython has two: the classic
    ``sys.settrace`` hook (what ``coverage``'s C tracer still uses
    on 3.13 — verified) and PEP-669 ``sys.monitoring`` (what
    ``COVERAGE_CORE=sysmon`` and future coverage releases use).
    Checking only one of them would silently stop catching the case
    the day the other becomes the default — which is precisely the
    kind of "the guard quietly stopped guarding" drift that let
    CI-01 sit red for weeks.
    """
    if sys.gettrace() is not None:
        return True
    monitoring = getattr(sys, "monitoring", None)  # PEP 669; 3.12+
    if monitoring is None:  # pragma: no cover - 3.11 and older
        return False
    for tool_id in range(6):  # PEP-669 tool ids are 0..5
        try:
            if monitoring.get_tool(tool_id) is not None:
                return True
        except ValueError:  # pragma: no cover - defensive
            continue
    return False


def _p99_ns(fn: Callable[[], None]) -> int:
    """Run `fn` `_MEASUREMENTS` times after a warmup, return the
    p99 of per-call duration in nanoseconds.

    Uses time.perf_counter_ns for monotonic, sub-µs-resolution
    measurement. p99 (not mean / median) is the right shape for a
    UI-budget pin: an occasional outlier is fine; consistent
    slowdown isn't.

    Skips outright under a tracer: the number we would compute is
    the tracer's per-line cost, not the helper's (see the module
    docstring / FEEDBACK CI-01). Asserting a real budget against a
    fake measurement is worse than not asserting.
    """
    if _tracer_active():
        pytest.skip(
            "sub-µs latency pin is not measurable under a line tracer "
            "(coverage / debugger / profiler): the tracer's per-line hook "
            "inflates these helpers ~4-5x, so the number measured would be "
            "the tracer, not mgf.hrb.fmt. Exercised for real by the un-traced "
            "lanes — plain `pytest -m perf` and the nightly-tier-0-3 step."
        )
    # Warmup — fills the CPython opcode cache + the JIT-equivalent
    # interpreter dispatch table. Without it, the first calls
    # measure interpreter startup, not steady-state.
    for _ in range(_WARMUP):
        fn()
    samples: list[int] = []
    for _ in range(_MEASUREMENTS):
        t0 = time.perf_counter_ns()
        fn()
        samples.append(time.perf_counter_ns() - t0)
    samples.sort()
    return samples[int(len(samples) * 0.99)]


def test_format_uptime_p99_under_1us() -> None:
    p99 = _p99_ns(lambda: format_uptime(3_725_000))  # "1h 2m 5s" path
    assert p99 < _BUDGET_NS, (
        f"format_uptime p99 = {p99} ns; budget = {_BUDGET_NS} ns. "
        "A regression has slowed the hot-path render — the most "
        "common operator-visible UI tick path."
    )


def test_format_duration_p99_under_1us() -> None:
    p99 = _p99_ns(lambda: format_duration(1_200_000))  # ms→s band path
    assert p99 < _BUDGET_NS, f"format_duration p99 = {p99} ns; budget = {_BUDGET_NS} ns."


def test_format_rss_p99_under_1us() -> None:
    p99 = _p99_ns(lambda: format_rss(44_400_000))  # MiB band — common
    assert p99 < _BUDGET_NS, f"format_rss p99 = {p99} ns; budget = {_BUDGET_NS} ns."


def test_format_severity_glyph_p99_under_1us() -> None:
    p99 = _p99_ns(lambda: format_severity_glyph("fail"))
    assert p99 < _BUDGET_NS, f"format_severity_glyph p99 = {p99} ns; budget = {_BUDGET_NS} ns."


def test_fmt_module_cold_import_under_5ms() -> None:
    """Cold-import budget. fmt is imported by hrb-app's view layer
    + the CLI doctor command + (eventually) every UI consumer in
    the federation. A slow cold-import slows app startup."""
    # Evict the module so we measure a true cold import.
    for mod in [m for m in list(sys.modules) if m == "mgf.hrb.fmt"]:
        del sys.modules[mod]
    t0 = time.perf_counter_ns()
    importlib.import_module("mgf.hrb.fmt")
    elapsed_us = (time.perf_counter_ns() - t0) / 1000
    assert elapsed_us < 5_000, (  # 5 ms = 5000 µs
        f"mgf.hrb.fmt cold import took {elapsed_us:.0f} µs; "
        f"budget = 5000 µs. Something heavy was added to module top."
    )
