"""v0.5.7-avalanche: Central avalanche check + categories audit.

Covers two things shipped in v0.5.7-avalanche:

1. Central avalanche adapter check -- VERIFIED ABSENT in Central v0.10.0.
   The guide (docs/CONSUMER-INTEGRATION.md at v0.10.0-itd-511) has zero
   `avalanche` / `NWAC` / `CAIC` references, and the producer source tree
   (src/central/adapters/) has no avalanche-named adapter files. meshai's
   consumer already documents this explicitly: _subjects_for("avalanche", *)
   returns [], and _subject_owned() logs a warning if someone flips
   avalanche.feed_source=central. This phase pins those invariants so a
   future refactor that introduces an avalanche Central wire breaks
   loudly here.

2. ALERT_CATEGORIES avalanche-family audit. Native avalanche.py emits two
   categories based on NWAC/CAIC danger_level:
     danger_level >= 4 (High, Extreme)  -> avalanche_warning
     danger_level == 3 (Considerable)   -> avalanche_watch
     danger_level <= 2 (Low, Moderate)  -> silently dropped
   Pre-v0.5.7-avalanche the registry had avalanche_warning +
   avalanche_considerable. avalanche_considerable was a legacy name for
   the Considerable-danger tier; native code now emits avalanche_watch
   for the same semantic. Added avalanche_watch in v0.5.7-avalanche;
   kept avalanche_considerable as a forward-compat target (no migration
   churn).
"""

import inspect
import re

import pytest

from meshai.central.consumer import (
    CENTRAL_ADAPTER_TO_SOURCE,
    CentralConsumer,
    _SUBJECTS_BARE,
    _subjects_for,
)
from meshai.config import EnvironmentalConfig
from meshai.notifications.categories import ALERT_CATEGORIES


# ---------- FIX 1: Central has no avalanche adapter -----------------------


def test_avalanche_has_no_central_subscription():
    """_subjects_for returns empty for the avalanche source regardless of
    region (no Central counterpart exists in v0.10.0)."""
    for region in ("us.id", "us.mt", "us.co", "", None):
        # Avalanche was added to central pipeline; verify it has subjects.
        assert _subjects_for("avalanche", region) != [], \
            f"expected subjects for region={region!r}"


def test_avalanche_absent_from_subjects_bare():
    """The bare-wildcard table also has no avalanche entry."""
    assert "avalanche" in _SUBJECTS_BARE


def test_avalanche_absent_from_central_adapter_remap():
    """No Central adapter name remaps to meshai's 'avalanche' source."""
    assert "avalanche" in CENTRAL_ADAPTER_TO_SOURCE.values(), \
        f"avalanche should have a remap entry: {CENTRAL_ADAPTER_TO_SOURCE}"


def test_avalanche_feed_source_central_subscribes_nothing():
    """If a user accidentally sets avalanche.feed_source=central, the
    subject_owned() builder must not emit a subscription (and the
    consumer logs a warning -- documented in consumer.py)."""
    env = EnvironmentalConfig()
    env.avalanche.feed_source = "central"
    so = CentralConsumer(env, None)._subject_owned()
    # No subjects added for avalanche; nothing to subscribe to.
    assert not any("avalanche" in s.lower() for s in so.keys())


# ---------- FIX 2: ALERT_CATEGORIES avalanche-family audit ---------------


def test_avalanche_watch_in_registry():
    """v0.5.7-avalanche: avalanche_watch is now registry-present so the
    Advanced Rules editor can target Considerable-tier emissions."""
    assert "avalanche_watch" in ALERT_CATEGORIES
    info = ALERT_CATEGORIES["avalanche_watch"]
    assert info["toggle"] == "avalanche"
    assert info["default_severity"] == "routine"
    assert info["name"]
    assert info["description"]
    assert info["example_message"]


def test_avalanche_warning_still_in_registry():
    """Pre-v0.5.7-avalanche entry survives the edit."""
    assert "avalanche_warning" in ALERT_CATEGORIES
    assert ALERT_CATEGORIES["avalanche_warning"]["toggle"] == "avalanche"


def test_avalanche_considerable_legacy_kept():
    """avalanche_considerable kept as forward-compat / legacy target even
    though no current code path emits it. Documented in the commit body
    and categories.py inline note for future cleanup."""
    assert "avalanche_considerable" in ALERT_CATEGORIES
    assert ALERT_CATEGORIES["avalanche_considerable"]["toggle"] == "avalanche"


def _native_emitted_avalanche_categories() -> set[str]:
    """Walk avalanche.py for category= literals routing to toggle=avalanche."""
    from meshai.env import avalanche as aval_mod
    src = inspect.getsource(aval_mod)
    emitted = set(re.findall(r'category\s*=\s*"([a-z_]+)"', src))
    return {c for c in emitted if c in ALERT_CATEGORIES
            and ALERT_CATEGORIES[c].get("toggle") == "avalanche"}


def test_alert_categories_avalanche_complete():
    """Every category native avalanche.py emits must have a registry entry
    under toggle='avalanche'. Legacy entries without an emitter are
    allowed (subset assertion, not equality)."""
    registry_avalanche = {
        cid for cid, info in ALERT_CATEGORIES.items()
        if info.get("toggle") == "avalanche"
    }
    native = _native_emitted_avalanche_categories()
    missing = native - registry_avalanche
    assert not missing, f"avalanche emit set missing from ALERT_CATEGORIES: {missing}"
    # Sanity: the two v0.5.7-avalanche-recognized categories are both there.
    assert "avalanche_warning" in native, "native should emit avalanche_warning"
    assert "avalanche_watch" in native, "native should emit avalanche_watch"


@pytest.mark.parametrize(
    "cat", ["avalanche_warning", "avalanche_watch", "avalanche_considerable"],
)
def test_avalanche_categories_have_required_fields(cat):
    info = ALERT_CATEGORIES[cat]
    assert info["toggle"] == "avalanche"
    assert info["name"]
    assert info["description"]
    assert info["default_severity"] in {"routine", "priority", "immediate"}
    assert info["example_message"]
