"""TC-05: orchestrator-down detection.

A ``/metrics`` timeout / connection-refused / 5xx / unreadable body -> the
``orchestrator_down`` signal -> ALERT "орк не отвечает" once the debounce
threshold of consecutive failures is reached (FR-3).
"""
from watchdog.collectors import orch as orch_mod
from watchdog.config import Config
from watchdog.signals import orch_down_signal

from .conftest import http_error, make_opener


def _cfg(**kw):
    return Config.from_env({**{"WATCHDOG_ORCH_DOWN_TICKS": "3"}, **kw})


def test_fetch_timeout_is_not_ok():
    opener = make_opener(exc=TimeoutError("timed out"))
    res = orch_mod.fetch_metrics("http://x/metrics", 1.0, opener=opener)
    assert res.ok is False
    assert res.envelope is None
    assert res.error


def test_fetch_connection_refused_is_not_ok():
    opener = make_opener(exc=ConnectionRefusedError("refused"))
    res = orch_mod.fetch_metrics("http://x/metrics", 1.0, opener=opener)
    assert res.ok is False


def test_fetch_5xx_is_not_ok():
    opener = make_opener(status=503, body=b"oops")
    res = orch_mod.fetch_metrics("http://x/metrics", 1.0, opener=opener)
    assert res.ok is False
    assert "503" in (res.error or "")


def test_fetch_httperror_5xx_is_not_ok():
    opener = make_opener(exc=http_error(502))
    res = orch_mod.fetch_metrics("http://x/metrics", 1.0, opener=opener)
    assert res.ok is False


def test_fetch_unreadable_body_is_not_ok():
    opener = make_opener(status=200, body=b"not-json{{{")
    res = orch_mod.fetch_metrics("http://x/metrics", 1.0, opener=opener)
    assert res.ok is False


def test_fetch_good_body_is_ok():
    opener = make_opener(status=200, body=b'{"schema_version":1,"stages":[]}')
    res = orch_mod.fetch_metrics("http://x/metrics", 1.0, opener=opener)
    assert res.ok is True
    assert res.envelope["schema_version"] == 1


def test_orch_down_signal_debounce_then_alert():
    cfg = _cfg()
    # Single transient failure -> NOT active (does not flap).
    assert orch_down_signal(1, cfg, "timeout").active is False
    assert orch_down_signal(2, cfg, "timeout").active is False
    # K-th consecutive failure -> active alarm.
    sig = orch_down_signal(3, cfg, "timeout")
    assert sig.active is True
    assert sig.key == "orch_down"
    assert "не отвечает" in sig.detail
