"""Pins for `mgf.hrb.exceptions.from_wire` shape + rate-limit (O1).

`from_wire` is the single hot translation point from wire-err
strings to typed Python exceptions. Three contracts to pin:

  1. **Known codes** map to the documented exception class.
  2. **Unknown codes** degrade to the generic `MgfHrbError`, with
     a WARNING log emitted exactly ONCE per (process, code) pair
     so a buggy / version-skewed broker can't flood the SDK log.
  3. **Non-string `err` field** (broker-bug shape) coerces to
     "Unknown" without raising — same once-per-process WARNING.

The rate-limit (O1, review wave 3) is the regression target: a
prior implementation would have emitted one WARNING per call,
which under sustained skew could drown the operator log at
thousands of lines per second.
"""

from __future__ import annotations

import logging

import pytest

from mgf.hrb.exceptions import (
    BadRequestError,
    HardwareFaultError,
    MgfHrbError,
    NotFoundError,
    NotPermittedError,
    RevokedError,
    from_wire,
)

# --- Known-code mapping ---------------------------------------------------


@pytest.mark.parametrize(
    ("wire_code", "expected_cls"),
    [
        ("NotFound", NotFoundError),
        ("NotPermitted", NotPermittedError),
        ("BadRequest", BadRequestError),
        ("HardwareFault", HardwareFaultError),
        ("Revoked", RevokedError),
    ],
)
def test_known_codes_map_to_typed_exceptions(
    wire_code: str, expected_cls: type[MgfHrbError]
) -> None:
    """Every documented wire-err code maps to its typed exception
    class. Catches a regression where a code was removed from
    `_WIRE_TO_EXC` without anyone noticing — consumers' `except
    NotPermittedError:` branches would suddenly miss the typed
    error and fall through to generic `MgfHrbError`."""
    exc = from_wire(wire_code)
    assert isinstance(exc, expected_cls)
    # Every subclass of MgfHrbError must catch via the root.
    assert isinstance(exc, MgfHrbError)
    # The original wire string survives as the exception message.
    assert str(exc) == wire_code


# --- Unknown-code rate-limit (O1) ----------------------------------------


def test_unknown_code_warns_once_per_process(
    caplog: pytest.LogCaptureFixture,
) -> None:
    """A previously-unseen wire-err code triggers exactly ONE
    WARNING log line; subsequent calls with the same code degrade
    silently (no further logs). This is the O1 rate-limit.

    Implementation note: the dedup set is module-level, so we
    use a unique code per test invocation to avoid cross-test
    pollution (the set is intentionally not test-clearable —
    it's the once-per-process semantic we want to preserve)."""
    # Unique-per-test code so set state from other tests doesn't bias.
    unique_code = "TestOnly_O1_OneShot_UniqueA"
    caplog.set_level(logging.WARNING, logger="mgf.hrb.exceptions")

    # Three calls with the same unknown code.
    e1 = from_wire(unique_code)
    e2 = from_wire(unique_code)
    e3 = from_wire(unique_code)

    # All three produce a generic MgfHrbError (no typed subclass).
    for e in (e1, e2, e3):
        assert isinstance(e, MgfHrbError)
        assert type(e) is MgfHrbError  # NOT a subclass

    # Exactly one WARNING record was emitted for this code.
    matching = [
        rec
        for rec in caplog.records
        if rec.levelno == logging.WARNING and unique_code in rec.getMessage()
    ]
    assert len(matching) == 1, (
        f"expected exactly one WARNING for unknown code "
        f"{unique_code!r}, got {len(matching)}: {[r.getMessage() for r in matching]}"
    )


def test_different_unknown_codes_each_warn_once(
    caplog: pytest.LogCaptureFixture,
) -> None:
    """Distinct unknown codes each get their own first-sight
    WARNING. This proves the dedup is keyed on the code string,
    not "first unknown ever"."""
    code_a = "TestOnly_O1_DistinctA"
    code_b = "TestOnly_O1_DistinctB"
    caplog.set_level(logging.WARNING, logger="mgf.hrb.exceptions")

    from_wire(code_a)
    from_wire(code_b)
    from_wire(code_a)  # duplicate — must NOT re-warn
    from_wire(code_b)  # duplicate — must NOT re-warn

    matching_a = [
        rec
        for rec in caplog.records
        if rec.levelno == logging.WARNING and code_a in rec.getMessage()
    ]
    matching_b = [
        rec
        for rec in caplog.records
        if rec.levelno == logging.WARNING and code_b in rec.getMessage()
    ]
    assert len(matching_a) == 1
    assert len(matching_b) == 1


# --- Non-string err defensive coercion ----------------------------------


def test_non_string_err_coerces_without_raising() -> None:
    """A broker bug sending `"err": null` or `"err": 42` must NOT
    crash the SDK before the consumer's `except MgfHrbError:`
    handler runs. The wire-err value coerces to the literal
    "Unknown" and the call returns a generic MgfHrbError."""
    # null
    exc = from_wire(None)  # type: ignore[arg-type]
    assert isinstance(exc, MgfHrbError)
    # int
    exc = from_wire(42)  # type: ignore[arg-type]
    assert isinstance(exc, MgfHrbError)
    # list
    exc = from_wire(["NotFound"])  # type: ignore[arg-type]
    assert isinstance(exc, MgfHrbError)
