"""Concurrency / thread-safety pins for ``mgf.hrb.fmt`` — PR-* test
plan T4 / hardening reliability invariant.

The fmt module docstring claims: *"Pure functions; no module-level
mutable state; safe for concurrent use."* If a future maintainer
adds a cache "for performance" without coordination, the invariant
silently breaks — a thread-race might return one thread's output
when called from another, or worse, produce wrong output under
contention.

These tests spawn many threads each calling every helper many
times with mixed inputs; the assertions are:

1. **Determinism under contention.** For each (helper, input), the
   output from a threaded call equals the single-threaded reference.
2. **No exceptions.** Any helper raising under contention is a
   regression — the helpers are pure and shouldn't fault.

Marked ``@pytest.mark.concurrency`` so they're tier-2 (not in the
default suite); run them with ``pytest -m concurrency`` or as part
of the full conformance gate.
"""

from __future__ import annotations

import random
import sys
from concurrent.futures import ThreadPoolExecutor, as_completed

import pytest

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

pytestmark = pytest.mark.concurrency


_THREADS = 16
_CALLS_PER_THREAD = 5_000


def _stress_uptime(seed: int) -> dict[int, str]:
    """Per-thread sample: call format_uptime over a varied range,
    return {input: output} for cross-thread comparison."""
    rng = random.Random(seed)  # noqa: S311 — test fixture, not crypto
    results: dict[int, str] = {}
    for _ in range(_CALLS_PER_THREAD):
        v = rng.randint(0, 10**11)  # broad range covering all bands
        results[v] = format_uptime(v)
    return results


def _stress_duration(seed: int) -> dict[int, str]:
    rng = random.Random(seed)  # noqa: S311 — test fixture, not crypto
    results: dict[int, str] = {}
    for _ in range(_CALLS_PER_THREAD):
        v = rng.randint(0, 10**11)
        results[v] = format_duration(v)
    return results


def _stress_rss(seed: int) -> dict[int, str]:
    rng = random.Random(seed)  # noqa: S311 — test fixture, not crypto
    results: dict[int, str] = {}
    for _ in range(_CALLS_PER_THREAD):
        v = rng.randint(0, 10**15)
        results[v] = format_rss(v)
    return results


def _stress_glyph(seed: int) -> dict[str, str]:
    rng = random.Random(seed)  # noqa: S311 — test fixture, not crypto
    keys = ("ok", "warn", "fail", "deferred", "unknown1", "unknown2")
    results: dict[str, str] = {}
    for _ in range(_CALLS_PER_THREAD):
        k = rng.choice(keys)
        results[k] = format_severity_glyph(k)
    return results


@pytest.mark.parametrize(
    ("helper_name", "stress_fn", "reference_fn"),
    [
        ("format_uptime", _stress_uptime, format_uptime),
        ("format_duration", _stress_duration, format_duration),
        ("format_rss", _stress_rss, format_rss),
        ("format_severity_glyph", _stress_glyph, format_severity_glyph),
    ],
)
def test_helper_is_deterministic_under_thread_contention(
    helper_name: str,
    stress_fn: object,
    reference_fn: object,
) -> None:
    """For every input observed in ANY thread, the helper's output
    equals the single-threaded reference output. Any divergence
    implies hidden state — a regression."""
    del helper_name  # used only for parametrize id readability
    union: dict[object, str] = {}
    with ThreadPoolExecutor(max_workers=_THREADS) as pool:
        futures = [pool.submit(stress_fn, seed) for seed in range(_THREADS)]  # type: ignore[operator]
        for fut in as_completed(futures):
            thread_results = fut.result()
            for inp, out in thread_results.items():
                if inp in union:
                    assert union[inp] == out, (
                        f"thread-race: same input {inp!r} produced "
                        f"two outputs: {union[inp]!r} vs {out!r}"
                    )
                else:
                    union[inp] = out
    # Cross-check every observed input against a fresh single-thread
    # call. If contention-time output diverges from reference output,
    # something shared (a cache, a lazy global) is leaking.
    for inp, threaded_out in union.items():
        ref_out = reference_fn(inp)  # type: ignore[operator]
        assert ref_out == threaded_out, (
            f"contention output {threaded_out!r} != reference {ref_out!r} for input {inp!r}"
        )


def test_helpers_have_no_module_level_mutable_state() -> None:
    """Belt-and-braces structural check: the fmt module exposes no
    module-level mutable container (list, dict, set) at write
    surface. Module-level dicts ARE allowed as read-only lookups
    (the ``_SEVERITY_GLYPHS`` dict is one), but a future
    contributor adding ``_CACHE = {}`` triggers this test by
    failing the value-equality check below — we list every dict/
    list/set at module scope here so anything new shows up as a
    diff."""
    import mgf.hrb.fmt as fmt_mod

    mutable_attrs = {
        name: type(getattr(fmt_mod, name)).__name__
        for name in dir(fmt_mod)
        if not name.startswith("__") and isinstance(getattr(fmt_mod, name), dict | list | set)
    }
    # The known read-only lookups. If a new entry appears here, this
    # test fails — that's the signal to either (a) prove it's read-
    # only and add it here, or (b) move it out of module scope.
    assert mutable_attrs == {
        "_SEVERITY_GLYPHS": "dict",
    }, (
        f"fmt module gained a new module-level mutable container: "
        f"{mutable_attrs}. If it's read-only by convention, "
        f"add it to the allow-list in this test. If not, move it "
        f"into the function it's used by."
    )


def test_uptime_helper_under_extreme_concurrency_does_not_raise() -> None:
    """Burn-in: 16 threads x 5k calls each = 80k calls; assert none
    of them raised. Catches transient locking faults that a small
    seed-range might miss."""
    errors: list[BaseException] = []

    def worker() -> None:
        try:
            for v in range(0, 10_000_000, 137):  # arbitrary stride
                format_uptime(v)
                format_duration(v)
                format_rss(v * 1024)
        except BaseException as exc:
            errors.append(exc)

    with ThreadPoolExecutor(max_workers=_THREADS) as pool:
        futures = [pool.submit(worker) for _ in range(_THREADS)]
        for fut in as_completed(futures):
            fut.result()

    assert not errors, f"helpers raised under contention: {errors[:3]}"
    # Sanity: we actually ran. sys.maxsize / 1e7 ≈ 922 trillion iters
    # if loop ever silently exited, the test stays green falsely;
    # confirm at least one call happened.
    assert format_uptime(1_000) == "1s"


_ = sys  # quiet "unused-import" if no maxsize ref above
