import pytest

import translate
from translate import Registry, ReplayNeeded, deliver, render_envelope, session_key

TOOLS = [{"name": "run_command"}, {"name": "read_file"}]
BASE = [{"role": "system", "content": "be terse"},
        {"role": "user", "content": "count the py files"}]


def test_key_is_stable_for_the_same_session():
    assert session_key(BASE, TOOLS, "medium") == session_key(
        BASE + [{"role": "assistant", "content": "…"}], TOOLS, "medium")


@pytest.mark.parametrize("messages,tools,effort", [
    (BASE, TOOLS, "high"),
    ([{"role": "system", "content": "be verbose"}, BASE[1]], TOOLS, "medium"),
    ([BASE[0], {"role": "user", "content": "something else"}], TOOLS, "medium"),
    (BASE, TOOLS + [{"name": "write_file"}], "medium"),
])
def test_any_change_including_effort_changes_the_key(messages, tools, effort):
    assert session_key(messages, tools, effort) != session_key(BASE, TOOLS, "medium")


def test_delivering_a_matching_prefix_types_only_the_suffix():
    conv = Registry().open("k", "preamble", "medium")
    conv.delivered = list(BASE)
    text = deliver(conv, BASE + [{"role": "tool", "tool_call_id": "call_0_a", "content": "8"},
                                 {"role": "user", "content": "now what"}])
    assert text == "TOOL RESULT [call_0_a]\n8\n\nUSER\nnow what"
    assert len(conv.delivered) == 4


def test_rewritten_history_demands_a_replay():
    conv = Registry().open("k", "preamble", "medium")
    conv.delivered = list(BASE)
    with pytest.raises(ReplayNeeded):
        deliver(conv, [BASE[0], {"role": "user", "content": "a compacted summary"}])


def test_shortened_history_demands_a_replay():
    conv = Registry().open("k", "preamble", "medium")
    conv.delivered = list(BASE)
    with pytest.raises(ReplayNeeded):
        deliver(conv, BASE[:1])


def test_envelope_renders_every_result_then_the_user_turn():
    text = render_envelope([
        {"role": "tool", "tool_call_id": "a", "content": "one"},
        {"role": "tool", "tool_call_id": "b", "content": "two"},
        {"role": "user", "content": "go on"},
    ])
    assert text == ("TOOL RESULT [a]\none\n\nTOOL RESULT [b]\ntwo\n\nUSER\ngo on")


def test_oversized_result_is_elided_in_the_middle():
    content = "x" * (translate.MAX_RESULT_CHARS + 100)
    out = translate.elide(content)
    assert "…100 chars elided…" in out
    assert out.startswith("x") and out.endswith("x")
    assert len(out) < len(content)


def test_registry_tracks_open_conversations():
    reg = Registry()
    assert reg.get("k") is None
    conv = reg.open("k", "preamble", "high")
    assert reg.get("k") is conv and conv.effort == "high" and len(reg) == 1
    reg.drop("k")
    assert reg.get("k") is None
