"""Tests from Lab 09's real calls. Run: pytest test_agent_practice.py"""
import math

from agent_practice import spoken_digits, task_result, turn_latency, wilson


def test_flux_heard_all_ten_digits():
    # numbers_spoken: what the caller said, and what Flux wrote down
    assert spoken_digits("nine one nine, five five five, oh one fifty") == "9195550150"
    assert spoken_digits("Sure, it's nine one nine five five five zero one five zero.") == "9195550150"
    assert spoken_digits("415-555-0123") == "4155550123"


def test_the_real_stt_error_four_fives_heard_as_three():
    heard = spoken_digits("Yes. It's four one five five five zero one two three")
    assert heard == "415550123" and len(heard) == 9


def test_tens_and_teens():
    assert spoken_digits("call me at fifty five, twelve") == "5512"
    assert spoken_digits("ninety oh one") == "9001"


EXPECT_OMAR = {"appointment": {"name": "Omar Haddad", "phone": "9195550150", "date": "2026-10-09", "time": "16:00"}}


def test_nothing_booked_after_twelve_turns():
    # numbers_spoken, run 2: the LLM sent 91955501502 and 919555015012 to the tool; nothing booked
    tools = ["book_appointment", "book_appointment", "book_appointment"]
    assert task_result([], tools, EXPECT_OMAR) == {"success": False, "problems": ["no appointment"]}


def test_haddad_booked_as_hadad():
    final = [{"id": "A100", "name": "Omar Hadad", "phone": "9195550150", "date": "2026-10-09", "time": "16:00"}]
    assert task_result(final, ["book_appointment"], EXPECT_OMAR) == {"success": False, "problems": ["wrong name"]}
    final[0]["name"] = "omar haddad"
    assert task_result(final, ["book_appointment"], EXPECT_OMAR)["success"] is True


def test_cancel_rules_on_the_tool_log():
    expect = {"absent": "A1", "tools_before": {"cancel_appointment": ["find_appointment"]},
              "forbidden_tools": ["book_appointment"]}
    assert task_result([], ["find_appointment", "cancel_appointment", "end_call"], expect)["success"] is True
    assert task_result([], ["cancel_appointment"], expect)["problems"] == ["cancel_appointment before find_appointment"]
    seeded = [{"id": "A1", "name": "Tom Becker", "phone": "2065550139", "date": "2026-10-07", "time": "11:00"}]
    assert task_result(seeded, ["find_appointment", "book_appointment"], expect)["problems"] == \
        ["not cancelled", "called book_appointment"]


def test_turn_latency_from_a_real_turn():
    # numbers_spoken, run 0, the agent's first reply
    turn = {"caller_speech_end": 10.0918, "eot": 10.9773, "llm_first_token": 11.5307,
            "first_sentence": 11.7086, "tts_first_byte": 11.8679, "play_start": 11.9679,
            "leading_silence": 0.0673}
    lat = turn_latency(turn)
    assert math.isclose(lat["endpointing"], 0.8855, abs_tol=1e-4)
    assert math.isclose(lat["llm_first_token"], 0.5534, abs_tol=1e-4)
    assert math.isclose(lat["playback_and_lead"], 0.1673, abs_tol=1e-4)
    assert math.isclose(lat["voice_to_voice"], 1.9434, abs_tol=1e-4)
    stages = ["endpointing", "llm_first_token", "first_sentence_ready", "tts_first_byte", "playback_and_lead"]
    assert math.isclose(sum(lat[s] for s in stages), lat["voice_to_voice"], abs_tol=1e-9)


def test_five_of_five_is_not_proof():
    lo, hi = wilson(5, 5)
    assert round(lo, 2) == 0.57 and hi == 1.0
    lo, hi = wilson(0, 5)
    assert lo == 0.0 and round(hi, 2) == 0.43


def test_v1_and_v2_intervals_overlap():
    v1, v2 = wilson(29, 40), wilson(32, 40)
    assert [round(x, 2) for x in v1] == [0.57, 0.84]
    assert [round(x, 2) for x in v2] == [0.65, 0.9]
    assert v2[0] < v1[1]
