"""TC-07: kill-switch + env-driven config (no hardcoded thresholds).

``WATCHDOG_ENABLED=false`` -> the daemon is inert (idle, no ticks). Thresholds /
intervals / timeouts come from env, not constants.
"""
from watchdog.config import Config


def test_killswitch_off_is_inert(monkeypatch):
    from watchdog import __main__ as entry

    cfg = Config.from_env({"WATCHDOG_ENABLED": "false", "WATCHDOG_INTERVAL_S": "0"})
    assert cfg.enabled is False

    built = {"n": 0}

    class _Dog:
        def tick(self):
            built["n"] += 1

    # If run() ever constructed a Watchdog / ticked while disabled, this would fire.
    monkeypatch.setattr(entry, "Watchdog", lambda c: _Dog())
    monkeypatch.setattr(entry.time, "sleep", lambda *_: None)
    entry.run(cfg=cfg, max_ticks=3)
    assert built["n"] == 0  # inert: never ticked


def test_thresholds_read_from_env():
    cfg = Config.from_env(
        {
            "WATCHDOG_INTERVAL_S": "7",
            "WATCHDOG_MEM_PCT": "77",
            "WATCHDOG_QUEUE_DEPTH": "9",
            "WATCHDOG_AGENT_HUNG_MIN": "5",
            "WATCHDOG_STAGE_STUCK_MIN": "11",
            "WATCHDOG_ORCH_DOWN_TICKS": "4",
            "WATCHDOG_COOLDOWN_S": "60",
            "WATCHDOG_HTTP_TIMEOUT_S": "2",
            "WATCHDOG_CONTAINERS": "orchestrator,plane-app",
            "WATCHDOG_DEPS": "gitea=http://g/healthz,plane=http://p/",
        }
    )
    assert cfg.interval_s == 7.0
    assert cfg.mem_pct == 77.0
    assert cfg.queue_depth == 9
    assert cfg.agent_hung_s == 5 * 60.0
    assert cfg.stage_stuck_s == 11 * 60.0
    assert cfg.orch_down_ticks == 4
    assert cfg.cooldown_s == 60.0
    assert cfg.http_timeout_s == 2.0
    assert cfg.containers == ["orchestrator", "plane-app"]
    assert cfg.deps == {"gitea": "http://g/healthz", "plane": "http://p/"}


def test_defaults_when_env_absent():
    cfg = Config.from_env({})
    assert cfg.enabled is True
    assert cfg.interval_s == 30.0
    assert cfg.metrics_url.endswith(":8500/metrics")
    assert cfg.disk_crit_enabled is False
    assert cfg.containers == ["orchestrator"]
    assert cfg.deps == {}


def test_malformed_env_degrades_to_default():
    # A garbage numeric value must not crash config; it degrades to the default.
    cfg = Config.from_env({"WATCHDOG_INTERVAL_S": "abc", "WATCHDOG_MEM_PCT": ""})
    assert cfg.interval_s == 30.0
    assert cfg.mem_pct == 90.0


# -- ORCH-111: proc_blocking config (kill-switch default-off + safe threshold) --
def test_proc_blocking_defaults_off_and_safe():
    cfg = Config.from_env({})
    assert cfg.proc_enabled is False  # opt-in (needs `pid: host`)
    assert cfg.proc_patterns == ["pytest"]
    assert cfg.proc_cooldown_s == 1800.0
    # Cross-invariant (adr-0041 D2): the default age threshold MUST exceed the max
    # legitimate test-run budget max(merge_retest_timeout_s=600, coverage=900).
    assert cfg.proc_age_s > 900.0


def test_proc_blocking_thresholds_read_from_env():
    cfg = Config.from_env(
        {
            "WATCHDOG_PROC_ENABLED": "true",
            "WATCHDOG_PROC_AGE_MIN": "45",
            "WATCHDOG_PROC_PATTERNS": "pytest,coverage run",
            "WATCHDOG_PROC_COOLDOWN_S": "900",
        }
    )
    assert cfg.proc_enabled is True
    assert cfg.proc_age_s == 45 * 60.0
    assert cfg.proc_patterns == ["pytest", "coverage run"]
    assert cfg.proc_cooldown_s == 900.0


def test_proc_blocking_malformed_env_degrades():
    cfg = Config.from_env({"WATCHDOG_PROC_AGE_MIN": "nope", "WATCHDOG_PROC_ENABLED": ""})
    assert cfg.proc_age_min == 60.0
    assert cfg.proc_enabled is False
