"""PC-01: cold-start `import mgf.common` perf gate.

The library's import-time cost is paid by every CLI invocation
of every consumer. Every dev-machine run of a quick script that
needs `mgf.common.app_name()` (etc) waits for the import before
useful work starts. Multiply by every consumer's every CLI hook
across the federation.

PC-01 closed this gap by deferring the `MgfSettings` import
from module-load time to first-use time (inside `bootstrap()`).
This test pins the gain so a future refactor that reintroduces
the eager-import path fails CI loudly rather than re-introducing
the regression silently.

Marker: ``perf`` — runs in the nightly sweep, not on every PR.
The budget is generous (current × ~3) per the RA-11 + LG-12
discipline: catch order-of-magnitude regressions, not noise.

References:
- ``docs/inprogress/PERFORMANCE_AND_CAPACITY.md`` PC-01 work unit
- ``docs/standards/TESTING.md`` §8.4 (perf marker convention)
- ``docs/standards/TESTING.md`` §8.5 (generous-budget rationale)
"""

from __future__ import annotations

import statistics
import subprocess
import sys
import time

import pytest

pytestmark = pytest.mark.perf


# Measured 2026-05-15 on Linux 6.17 / Python 3.12.3:
#   import mgf.common ≈ 17-19 ms (post-PC-01 deferral)
#   Pre-PC-01 baseline was ≈ 100 ms cumulative.
#
# Budget: 60 ms = ~3× the measured value. CI hardware noise +
# Python-version drift can shift the absolute number by 1.5-2×;
# 60 ms catches the ~3-5× regression that would mean the
# settings-eager-import path has been silently reintroduced.
_IMPORT_MGF_COMMON_BUDGET_MS = 60.0


def _measure_import_ms() -> float:
    """Spawn a fresh interpreter and time `import mgf.common`.

    A fresh subprocess is mandatory — the parent test runner has
    already imported mgf.common at collection time, so any
    in-process `time.perf_counter()` around `import` would
    measure zero (sys.modules cache hits).
    """
    start = time.perf_counter()
    subprocess.run(
        [sys.executable, "-c", "import mgf.common"],
        check=True,
        capture_output=True,
    )
    return (time.perf_counter() - start) * 1000.0


class TestPC01ImportTime:
    """PC-01: `import mgf.common` cold-start budget."""

    def test_import_under_budget(self) -> None:
        """Median over 5 fresh-subprocess runs MUST stay under the
        ``_IMPORT_MGF_COMMON_BUDGET_MS`` cap.

        Why median over 5 runs: a single subprocess spawn includes
        Python interpreter startup overhead that can spike on a
        loaded CI runner. The median drops the worst outlier
        without falsifying the signal — a regression that shifts
        the whole distribution up will still trip the gate.
        """
        # One warm-up run to settle the system page cache.
        _measure_import_ms()

        measurements = [_measure_import_ms() for _ in range(5)]
        median_ms = statistics.median(measurements)

        assert median_ms < _IMPORT_MGF_COMMON_BUDGET_MS, (
            f"PC-01: `import mgf.common` budget breach: "
            f"median {median_ms:.1f} ms over 5 runs "
            f"(budget {_IMPORT_MGF_COMMON_BUDGET_MS:.0f} ms). "
            f"All measurements: "
            f"{[round(m, 1) for m in measurements]}. "
            f"Common cause: a top-level `from mgf.common.settings "
            f"import MgfSettings` or similar reintroduced the "
            f"pydantic + pydantic-settings eager-import chain. "
            f"Check src/mgf/common/_lifecycle.py + "
            f"_test_helpers.py — the PC-01 fix moved both under "
            f"`if TYPE_CHECKING:` with lazy in-function imports."
        )
