"""Tests for ConsecutiveAgentTermination."""

import pytest

from agentbyte.messages import AssistantMessage, UserMessage
from agentbyte.termination.consecutive_agent import ConsecutiveAgentTermination


def _msg(source: str, content: str = "x") -> AssistantMessage:
    return AssistantMessage(content=content, source=source)


class TestConsecutiveAgentTermination:
    def test_terminates_after_max_consecutive_same_source(self):
        term = ConsecutiveAgentTermination(max_consecutive=3)

        assert term.check([_msg("researcher")]) is None
        assert term.check([_msg("researcher")]) is None
        stop = term.check([_msg("researcher")])
        assert stop is not None
        assert stop.metadata["agent"] == "researcher"
        assert stop.metadata["consecutive_count"] == 3

    def test_resets_count_on_different_source(self):
        term = ConsecutiveAgentTermination(max_consecutive=3)

        term.check([_msg("researcher")])
        term.check([_msg("researcher")])
        term.check([_msg("writer")])       # breaks the streak
        assert term.check([_msg("researcher")]) is None  # streak restarted

    def test_ignored_sources_do_not_break_streak(self):
        term = ConsecutiveAgentTermination(max_consecutive=3)

        term.check([_msg("researcher")])
        term.check([_msg("orchestrator")])  # ignored — streak continues
        term.check([_msg("researcher")])
        stop = term.check([_msg("researcher")])
        assert stop is not None
        assert stop.metadata["consecutive_count"] == 3

    def test_user_messages_ignored_by_default(self):
        term = ConsecutiveAgentTermination(max_consecutive=2)

        term.check([UserMessage(content="go", source="user")])
        term.check([_msg("researcher")])             # streak = 1
        term.check([UserMessage(content="continue", source="user")])  # ignored — streak stays
        # user message did NOT break the streak, so this is the 2nd consecutive researcher
        stop = term.check([_msg("researcher")])
        assert stop is not None
        assert stop.metadata["consecutive_count"] == 2

    def test_custom_ignored_sources(self):
        term = ConsecutiveAgentTermination(max_consecutive=2, ignored_sources=["router"])

        term.check([_msg("researcher")])
        term.check([_msg("router")])    # ignored
        stop = term.check([_msg("researcher")])
        assert stop is not None

    def test_empty_ignored_sources_tracks_all(self):
        term = ConsecutiveAgentTermination(max_consecutive=2, ignored_sources=[])

        term.check([_msg("orchestrator")])
        stop = term.check([_msg("orchestrator")])
        assert stop is not None

    def test_multiple_messages_in_single_check(self):
        term = ConsecutiveAgentTermination(max_consecutive=3)

        stop = term.check([_msg("researcher"), _msg("researcher"), _msg("researcher")])
        assert stop is not None
        assert stop.metadata["consecutive_count"] == 3

    def test_reset_clears_state(self):
        term = ConsecutiveAgentTermination(max_consecutive=2)

        term.check([_msg("researcher")])
        term.reset()

        assert term.check([_msg("researcher")]) is None  # count back to 1 after reset
        stop = term.check([_msg("researcher")])
        assert stop is not None

    def test_stop_message_contains_limit_info(self):
        term = ConsecutiveAgentTermination(max_consecutive=2)
        term.check([_msg("writer")])
        stop = term.check([_msg("writer")])

        assert stop is not None
        assert "writer" in stop.content
        assert stop.metadata["max_consecutive"] == 2

    def test_invalid_max_consecutive_raises(self):
        with pytest.raises(ValueError, match="max_consecutive"):
            ConsecutiveAgentTermination(max_consecutive=0)
