"""Standing negative fixtures for the perf comparator (PF-01/03/07/08, TS-29).

``Baselines.assert_no_regression`` is the decision every PF-01 budget in
``test_perf_pins.py`` delegates to, and nothing proved it *bites*. A
comparator that silently passed everything would leave every perf claim in
this repo vacuous and no test would notice — so these tests seed a regression
it must catch and pin the PF-07 numerics in the message.

**No ``perf`` marker, on purpose.** The benchmarks next door are excluded from
the default run (``-m "not perf"``, pyproject ``addopts``) because they take
seconds and want a quiet machine. This file needs neither — it is dict
arithmetic against a ``tmp_path`` baseline — and a self-test that ran only in
the nightly perf step would not be *standing* in the sense TS-29 means.

**The tier arms (PF-08, PAPER-154).** Since the comparator gained a third
outcome — *refuse* — the sabotage set grew to match. A cross-tier comparison
must not silently pass and must not silently fail, so both arms are seeded (a
40x regression and a healthy measurement, on a foreign tier: **both** must
skip). And because a skip renders no verdict, the mute itself is pinned: the
shipped ``baselines.json`` must be comparable on this repo's default tier, or
the local perf gate would be permanently silent and nothing would notice.
"""

from __future__ import annotations

import json
from pathlib import Path

import pytest

from tests.perf.conftest import (
    BASELINES_PATH,
    HW_TIER,
    Baselines,
    running_hw_tier,
)

_PERF_DIR = Path(__file__).resolve().parent
_SELF = Path(__file__).resolve()

_SEEDED_DESCRIPTION = "seeded metric for the comparator self-test"
_SEEDED_TIER = "seeded-tier"
# The tier `.woodpecker.yml`'s perf-nightly step declares — see hw_tiers.md.
_FOREIGN_TIER = "ci-amd64-small"


@pytest.fixture(autouse=True)
def _pin_the_env_the_comparator_reads(monkeypatch: pytest.MonkeyPatch) -> None:
    """Pin both env inputs, so no host can mute these tests.

    ``MGF_PERF_REBASELINE`` — a re-baseline run RECORDS instead of asserting,
    which would mute every test here.

    ``MGF_PERF_HW_TIER`` — since PF-08 enforcement landed, a running tier that
    disagrees with the seeded file's ``$hw_tier`` *skips* instead of comparing.
    Inherit the runner's value (CI sets it) and every test below would go
    green-by-skip — the exact trap the mechanism is supposed to close, sprung
    on the tests that prove it works. Pinning to the seeded tier makes the
    same-tier half of the contract explicit rather than accidental; the
    cross-tier tests override it deliberately.
    """
    monkeypatch.delenv("MGF_PERF_REBASELINE", raising=False)
    monkeypatch.setenv("MGF_PERF_HW_TIER", _SEEDED_TIER)


def _seeded_baselines(tmp_path: Path) -> Baselines:
    """One recorded metric: 2.5 us, +25% tolerance — so the limit is 3.125 us."""
    return Baselines(
        path=tmp_path / "baselines.json",
        data={
            "$schema_version": 1,
            "$updated_at": "2026-01-02T00:00:00+00:00",
            "$hw_tier": _SEEDED_TIER,
            "metrics": {
                "seeded_us_per_record": {
                    "value": 2.5,
                    "units": "us",
                    "recorded_at": "2026-01-02",
                    "recorded_commit": "0ddba11",
                    # Deliberately NOT the module default (150), so a message
                    # quoting +25% proves the per-metric override is the one used.
                    "regression_threshold_pct": 25,
                    "description": _SEEDED_DESCRIPTION,
                },
            },
        },
    )


class TestTheComparatorBites:
    def test_regression_fails_with_the_pf07_numerics(self, tmp_path: Path) -> None:
        """A 40x-over measurement must fail, and the message must carry the arithmetic."""
        baselines = _seeded_baselines(tmp_path)

        with pytest.raises(AssertionError) as excinfo:
            baselines.assert_no_regression(
                "seeded_us_per_record",
                100.0,
                units="us",
                description=_SEEDED_DESCRIPTION,
            )

        message = str(excinfo.value)
        for fragment in (
            "seeded_us_per_record regressed by +3900.0%",
            "baseline:  2.5 us",
            "measured:  100 us",
            "threshold: +25%",
            "hw_tier=seeded-tier",
            "recorded 2026-01-02",
            "commit 0ddba11",
            _SEEDED_DESCRIPTION,
        ):
            assert fragment in message, f"PF-07 message is missing {fragment!r}:\n{message}"

    def test_missing_baseline_fails_and_names_the_metric(self, tmp_path: Path) -> None:
        """PF-03 arm: an unrecorded metric is a failure, not a silent pass."""
        # Same-tier on purpose: the PF-08 refusal is checked before the row
        # lookup, so a foreign-tier file here would exercise that arm instead.
        baselines = Baselines(
            path=tmp_path / "baselines.json",
            data={"$hw_tier": _SEEDED_TIER, "metrics": {}},
        )

        with pytest.raises(AssertionError) as excinfo:
            baselines.assert_no_regression(
                "never_recorded_metric",
                1.0,
                units="us",
                description=_SEEDED_DESCRIPTION,
            )

        message = str(excinfo.value)
        for fragment in (
            "never_recorded_metric: no baseline recorded (PF-03)",
            "bench rebaseline never_recorded_metric",
            "baselines.json",
        ):
            assert fragment in message, f"PF-03 message is missing {fragment!r}:\n{message}"

    def test_measurement_inside_the_threshold_passes(self, tmp_path: Path) -> None:
        """Positive control — the comparator is not simply always-red.

        Without this, a comparator that raised unconditionally would satisfy
        both negatives above and still be useless.
        """
        _seeded_baselines(tmp_path).assert_no_regression(
            "seeded_us_per_record",
            3.0,  # under the 3.125 limit
            units="us",
            description=_SEEDED_DESCRIPTION,
        )


class TestTheTierRefusal:
    """PF-08 — three outcomes now, so three arms (PAPER-154)."""

    def test_cross_tier_regression_is_refused_not_silently_failed(
        self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
    ) -> None:
        """A 40x regression measured on a foreign tier must SKIP, not fail.

        Failing would be the seductive wrong answer — it looks strict. But
        PF-08 outlaws the comparison itself, so a red here would mean
        "different hardware", and a gate whose reds mean that is a gate people
        learn to ignore. The refusal must name both tiers so the reader can
        tell the two situations apart without reading the harness.
        """
        monkeypatch.setenv("MGF_PERF_HW_TIER", _FOREIGN_TIER)
        baselines = _seeded_baselines(tmp_path)

        with pytest.raises(pytest.skip.Exception) as excinfo:
            baselines.assert_no_regression(
                "seeded_us_per_record",
                100.0,  # 40x the 2.5 us baseline — a screaming red, same-tier
                units="us",
                description=_SEEDED_DESCRIPTION,
            )

        message = str(excinfo.value)
        for fragment in (
            "seeded_us_per_record: refusing a cross-tier perf comparison (PF-08)",
            f"running tier:   {_FOREIGN_TIER}",
            f"baselines tier: {_SEEDED_TIER}",
            "MGF_PERF_HW_TIER",
            "tests/perf/hw_tiers.md",
        ):
            assert fragment in message, f"PF-08 refusal is missing {fragment!r}:\n{message}"

    def test_cross_tier_healthy_measurement_is_refused_not_silently_passed(
        self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
    ) -> None:
        """The other half: a *comfortable* measurement on a foreign tier also skips.

        Without this arm, "cross-tier => green" would satisfy the test above
        and still be the exact vacuity PF-08 exists to prevent — an outlawed
        comparison quietly reported as a passing budget. This is the arm
        people forget.
        """
        monkeypatch.setenv("MGF_PERF_HW_TIER", _FOREIGN_TIER)
        baselines = _seeded_baselines(tmp_path)

        with pytest.raises(pytest.skip.Exception) as excinfo:
            baselines.assert_no_regression(
                "seeded_us_per_record",
                3.0,  # inside the same-tier limit — would have passed, and must not
                units="us",
                description=_SEEDED_DESCRIPTION,
            )

        assert "refusing a cross-tier perf comparison (PF-08)" in str(excinfo.value)

    def test_running_tier_is_declared_by_the_environment(
        self, monkeypatch: pytest.MonkeyPatch
    ) -> None:
        """`MGF_PERF_HW_TIER` names the running tier; blank/absent means the default."""
        monkeypatch.setenv("MGF_PERF_HW_TIER", _FOREIGN_TIER)
        assert running_hw_tier() == _FOREIGN_TIER
        monkeypatch.setenv("MGF_PERF_HW_TIER", "   ")
        assert running_hw_tier() == HW_TIER, "a blank declaration is not a tier named ''"
        monkeypatch.delenv("MGF_PERF_HW_TIER")
        assert running_hw_tier() == HW_TIER

    def test_the_shipped_baselines_are_comparable_on_the_default_tier(
        self, monkeypatch: pytest.MonkeyPatch
    ) -> None:
        """Mute pin: a skip renders NO verdict, so the silence itself needs a guard.

        If `HW_TIER` and `baselines.json`'s `$hw_tier` ever drift apart, every
        local `pytest -m perf` run goes green-by-skip and every perf budget in
        the repo stops being enforced anywhere — silently, forever. This is
        the test that notices, and it runs in the DEFAULT suite, not the perf
        tier, so the notice does not depend on the muted step.
        """
        monkeypatch.delenv("MGF_PERF_HW_TIER", raising=False)
        assert running_hw_tier() == HW_TIER
        shipped = Baselines.load()
        assert shipped.hw_tier == HW_TIER, (
            f"{BASELINES_PATH.name} carries $hw_tier={shipped.hw_tier!r} but the "
            f"default running tier is {HW_TIER!r} — every local perf comparison "
            f"would be skipped under PF-08 rather than run. Re-record the "
            f"baselines on this tier, or correct HW_TIER."
        )


class TestSaveRefusesToMixTiers:
    def test_save_refuses_to_mix_two_tiers_in_one_file(
        self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
    ) -> None:
        """A partial re-baseline on a new tier must not re-tag rows it never measured."""
        monkeypatch.setenv("MGF_PERF_REBASELINE", "1")
        monkeypatch.setenv("MGF_PERF_HW_TIER", _FOREIGN_TIER)
        baselines = _seeded_baselines(tmp_path)

        # Records ONE metric on the foreign tier; `seeded_us_per_record` is
        # left behind, still holding a `seeded-tier` measurement.
        baselines.assert_no_regression(
            "another_us_per_record", 9.0, units="us", description=_SEEDED_DESCRIPTION
        )

        with pytest.raises(AssertionError) as excinfo:
            baselines.save()

        message = str(excinfo.value)
        for fragment in (
            "refusing to re-tag baselines.json",
            _SEEDED_TIER,
            _FOREIGN_TIER,
            "'seeded_us_per_record'",
            "One baselines file carries one tier (PF-08)",
            "tests/perf/hw_tiers.md",
        ):
            assert fragment in message, f"mixing guard is missing {fragment!r}:\n{message}"
        assert not (tmp_path / "baselines.json").exists(), (
            "the half-true file must not have been written to disk"
        )

    def test_save_retags_the_file_when_every_metric_was_re_recorded(
        self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
    ) -> None:
        """Positive control for the guard — and the pin on the threshold-preserving rule.

        The re-baseline path re-records `value` but carries the existing
        `regression_threshold_pct` forward (``existing.get(...)``), so changing
        a threshold cannot be done by re-baselining alone. This is the
        assertion behind that behaviour.
        """
        monkeypatch.setenv("MGF_PERF_REBASELINE", "1")
        monkeypatch.setenv("MGF_PERF_HW_TIER", _FOREIGN_TIER)
        baselines = _seeded_baselines(tmp_path)

        baselines.assert_no_regression(
            "seeded_us_per_record", 9.0, units="us", description=_SEEDED_DESCRIPTION
        )
        baselines.save()

        written = json.loads((tmp_path / "baselines.json").read_text(encoding="utf-8"))
        assert written["$hw_tier"] == _FOREIGN_TIER, "the file records where it was measured"
        entry = written["metrics"]["seeded_us_per_record"]
        assert entry["value"] == 9.0, "the value is re-recorded"
        assert entry["regression_threshold_pct"] == 25, (
            "the threshold is PRESERVED, not reset to the module default — the "
            "behaviour that makes a threshold change a deliberate, separate act"
        )


class TestTheBaselineFileIsNotVacuous:
    def test_real_baselines_file_records_at_least_one_metric(self) -> None:
        """Vacuity pin: an empty baselines.json would make every budget a no-op."""
        assert BASELINES_PATH.is_file(), f"baselines file missing at {BASELINES_PATH}"
        data = json.loads(BASELINES_PATH.read_text(encoding="utf-8"))
        assert data.get("metrics"), (
            f"{BASELINES_PATH.name} records zero metrics — every PF-01 budget in "
            f"tests/perf/ is then either unrun or asserting against nothing. "
            f"Record one with `MGF_PERF_REBASELINE=1 pytest -m perf`."
        )

    def test_every_recorded_baseline_is_asserted_by_a_perf_test(self) -> None:
        """A baseline nothing asserts against is a claim with no gate behind it."""
        data = json.loads(BASELINES_PATH.read_text(encoding="utf-8"))
        # This file is excluded from the scan on purpose: it names no real
        # metric, and letting the self-test satisfy the pin would make it
        # circular.
        sources = "\n".join(
            path.read_text(encoding="utf-8")
            for path in sorted(_PERF_DIR.glob("test_*.py"))
            if path != _SELF
        )
        unasserted = sorted(name for name in data.get("metrics", {}) if name not in sources)
        assert not unasserted, (
            f"baselines.json records metrics that no tests/perf/test_*.py mentions: "
            f"{unasserted}. Either add the assertion or drop the row — a recorded "
            f"baseline with no test behind it guards nothing."
        )
