"""Tests from Lab 08's real results. Run: pytest test_monitor_practice.py"""
import math

from monitor_practice import canary_alerts, cusum, request_signals, window_z


def test_decoder_bug_decodes_to_half_length():
    # an 8 kHz phone upload declared as 4.3 s, read as 16 kHz: it decodes to half that
    s = request_signals("I have a day for time to go to school for the next hour", 4.3, 2.15)
    assert s["duration_mismatch"] is True
    assert s["empty"] is False
    assert math.isclose(s["words_per_second"], 14 / 4.3)
    # the same clip, decoded correctly: within 5%
    s = request_signals("I had again been acting under the influence of this man's power", 4.3, 4.31)
    assert s["duration_mismatch"] is False


def test_vad_setting_empty_transcript():
    s = request_signals("", 6.0, 6.0)
    assert s["empty"] is True and s["words_per_second"] == 0


def test_one_failure_at_3am_looks_like_18_sigma():
    p = 0.003  # a rare normal error rate
    sd = math.sqrt(p * (1 - p))
    assert round(window_z(1.0, 1, p, sd)) == 18     # 1 failed out of 1
    assert window_z(0.5, 2, p, sd) > 12              # 1 out of 2: still "a disaster"


def test_busy_windows_are_less_noisy():
    # the same 2-point drop in confidence means more in a window with 100 requests than with 4
    assert window_z(0.586, 100, 0.606, 0.2) < window_z(0.586, 4, 0.606, 0.2) < 0
    assert window_z(0.5, 0, 0.003, 0.05) == 0.0


def test_cusum_catches_a_small_persistent_shift():
    # z = 1 every window: no single window is extreme (a 3-sigma Shewhart never fires),
    # but the evidence adds up by 0.5 a window and passes h = 5 at the 11th window
    zs = [0.0] * 20 + [1.0] * 30
    assert cusum(zs, h=5) == [30, 43]
    # and it stays quiet on noise around normal
    assert cusum([0.4, -0.3, 0.6, -0.8, 0.2, 0.1, -0.5, 0.45] * 20, h=5) == []


def test_cusum_cooldown_counts_one_incident_once():
    zs = [10.0] * 30
    assert cusum(zs, h=5) == [0, 13, 26]


def test_canary_wrong_model_first_round():
    golden = {"wer": 9.2}
    normal = {"changed": 0, "errors": 0, "must_pass_failures": 0, "wer": 9.2}
    r3 = {"changed": 7, "errors": 0, "must_pass_failures": 1, "wer": 12.3}
    assert canary_alerts(normal, golden, normal) == []
    # round 3: the WER rule waits for a second bad round
    assert canary_alerts(r3, golden, normal) == ["transcripts changed", "must-pass"]
    # round 4: now WER too
    assert canary_alerts(r3, golden, r3) == ["transcripts changed", "must-pass", "wer"]


def test_canary_error_spike():
    golden = {"wer": 9.2}
    r13 = {"changed": 0, "errors": 1, "must_pass_failures": 0, "wer": 9.8}
    assert canary_alerts(r13, golden, r13) == ["requests failed"]
