import pytest

from yee88.context import RunContext
from yee88.model import ResumeToken
from yee88.telegram.topic_state import TopicStateStore


@pytest.mark.anyio
async def test_topic_state_store_roundtrip(tmp_path) -> None:
    path = tmp_path / "telegram_topics_state.json"
    store = TopicStateStore(path)
    context = RunContext(project="proj", branch="feat/topic")
    await store.set_context(1, 10, context)
    await store.set_default_engine(1, 10, "claude")
    await store.set_trigger_mode(1, 10, "mentions")
    await store.set_session_resume(1, 10, ResumeToken(engine="codex", value="abc123"))

    snapshot = await store.get_thread(1, 10)
    assert snapshot is not None
    assert snapshot.context == context
    assert snapshot.sessions == {"codex": "abc123"}
    assert snapshot.default_engine == "claude"
    assert await store.get_trigger_mode(1, 10) == "mentions"

    store2 = TopicStateStore(path)
    snapshot2 = await store2.get_thread(1, 10)
    assert snapshot2 is not None
    assert snapshot2.context == context
    assert snapshot2.sessions == {"codex": "abc123"}
    assert snapshot2.default_engine == "claude"
    assert await store2.get_trigger_mode(1, 10) == "mentions"


@pytest.mark.anyio
async def test_topic_state_store_clear_and_find(tmp_path) -> None:
    path = tmp_path / "telegram_topics_state.json"
    store = TopicStateStore(path)
    context = RunContext(project="proj", branch="main")
    await store.set_context(2, 20, context)
    await store.set_session_resume(
        2, 20, ResumeToken(engine="claude", value="resume-token")
    )

    found = await store.find_thread_for_context(2, context)
    assert found == 20

    await store.clear_sessions(2, 20)
    snapshot = await store.get_thread(2, 20)
    assert snapshot is not None
    assert snapshot.sessions == {}

    await store.clear_context(2, 20)
    snapshot = await store.get_thread(2, 20)
    assert snapshot is not None
    assert snapshot.context is None
    await store.clear_default_engine(2, 20)
    snapshot = await store.get_thread(2, 20)
    assert snapshot is not None
    assert snapshot.default_engine is None
    await store.clear_trigger_mode(2, 20)
    assert await store.get_trigger_mode(2, 20) is None


@pytest.mark.anyio
async def test_topic_state_store_delete_thread(tmp_path) -> None:
    path = tmp_path / "telegram_topics_state.json"
    store = TopicStateStore(path)
    context = RunContext(project="proj", branch="main")
    await store.set_context(1, 10, context)
    await store.set_session_resume(1, 10, ResumeToken(engine="codex", value="abc123"))

    await store.delete_thread(1, 10)

    assert await store.get_thread(1, 10) is None
    assert await store.find_thread_for_context(1, context) is None


@pytest.mark.anyio
async def test_topic_state_system_prompt_roundtrip(tmp_path) -> None:
    path = tmp_path / "telegram_topics_state.json"
    store = TopicStateStore(path)
    context = RunContext(project="proj", branch="main")
    await store.set_context(1, 10, context, system_prompt="be helpful")

    assert await store.get_system_prompt(1, 10) == "be helpful"

    snapshot = await store.get_thread(1, 10)
    assert snapshot is not None
    assert snapshot.system_prompt == "be helpful"

    # Persist across reload
    store2 = TopicStateStore(path)
    assert await store2.get_system_prompt(1, 10) == "be helpful"


@pytest.mark.anyio
async def test_topic_state_system_prompt_set_and_clear(tmp_path) -> None:
    path = tmp_path / "telegram_topics_state.json"
    store = TopicStateStore(path)
    context = RunContext(project="proj", branch="main")
    await store.set_context(1, 10, context)

    assert await store.get_system_prompt(1, 10) is None

    await store.set_system_prompt(1, 10, "new prompt")
    assert await store.get_system_prompt(1, 10) == "new prompt"

    await store.set_system_prompt(1, 10, None)
    assert await store.get_system_prompt(1, 10) is None


@pytest.mark.anyio
async def test_topic_state_system_prompt_not_set(tmp_path) -> None:
    path = tmp_path / "telegram_topics_state.json"
    store = TopicStateStore(path)

    assert await store.get_system_prompt(1, 99) is None
