"""Function call termination condition."""

from typing import List, Optional, Sequence

from agentbyte.messages import AssistantMessage, Message
from agentbyte.types import StopMessage

from .base import BaseTermination


class FunctionCallTermination(BaseTermination):
    """
    Terminates when a specific function/tool is called.

    Monitors assistant messages for tool calls and stops when
    a specified function is invoked.

    Example:
        # Stop when transfer_to_human is called
        termination = FunctionCallTermination(["transfer_to_human"])

        # Stop when any of multiple functions are called
        termination = FunctionCallTermination([
            "escalate_to_manager",
            "transfer_to_human",
            "end_conversation"
        ])
    """

    def __init__(self, function_names: List[str]):
        super().__init__()
        if not function_names:
            raise ValueError("At least one function name is required")
        self.function_names = set(function_names)

    def check(self, new_messages: Sequence[Message]) -> Optional[StopMessage]:
        """Check if any target function has been called."""
        for message in new_messages:
            # Check if this is an assistant message with tool calls
            if isinstance(message, AssistantMessage) and hasattr(message, "tool_calls"):
                if message.tool_calls:
                    for tool_call in message.tool_calls:
                        tool_name = (
                            tool_call.tool_name
                            if hasattr(tool_call, "tool_name")
                            else str(tool_call)
                        )

                        if tool_name in self.function_names:
                            return self._set_termination(
                                f"Target function called: '{tool_name}'",
                                {
                                    "function_name": tool_name,
                                    "target_functions": list(self.function_names),
                                },
                            )

        return None
