"""Role-playing agents for CAMEL framework."""

from dataclasses import dataclass, field
from typing import Any, Callable, Dict, List, Optional

from .types import Role, AgentType
from .conversation import Conversation, Message, MessageRole


@dataclass
class AgentRole:
    """Configuration for an agent's role."""
    role: Role
    system_prompt: str = ""
    goal: str = ""

    def get_full_prompt(self) -> str:
        """Get the complete system prompt."""
        parts = [self.role.get_system_prompt()]
        if self.system_prompt:
            parts.append(self.system_prompt)
        if self.goal:
            parts.append(f"\nYour goal: {self.goal}")
        return "\n\n".join(parts)


class RolePlayingAgent:
    """An agent that plays a specific role in a conversation.

    RolePlayingAgent implements the core concept of CAMEL: agents
    with defined roles that collaborate through structured dialogue.

    Example:
        >>> programmer = Role(name="Programmer", description="Writes code")
        >>> agent = RolePlayingAgent(role=programmer)
        >>> response = agent.respond("Write a function to sort a list")
    """

    def __init__(
        self,
        role: Role,
        respond_fn: Optional[Callable[[str, List[Dict]], str]] = None,
        conversation: Optional[Conversation] = None,
        verbose: bool = False,
    ):
        """Initialize the role-playing agent.

        Args:
            role: The role this agent plays
            respond_fn: Function to generate responses (takes context, messages)
            conversation: Optional conversation to join
            verbose: Whether to print debug info
        """
        self.role = role
        self._respond_fn = respond_fn or self._default_respond
        self._conversation = conversation or Conversation()
        self._verbose = verbose

    def respond(
        self,
        input_message: str,
        conversation: Optional[Conversation] = None,
    ) -> Message:
        """Generate a response as this role.

        Args:
            input_message: The message to respond to
            conversation: Optional conversation context

        Returns:
            The generated message
        """
        conv = conversation or self._conversation

        # Build context from conversation
        context = conv.get_context_string(max_messages=10)

        # Generate response
        if self._verbose:
            print(f"\n[{self.role.name}] Thinking...")

        messages = conv.get_openai_messages(include_system=False)
        response_content = self._respond_fn(context or input_message, messages)

        # Determine message role based on agent type
        msg_role = MessageRole.ASSISTANT
        if self.role.agent_type == AgentType.USER:
            msg_role = MessageRole.USER

        # Create and add message
        message = Message(
            content=response_content,
            role=msg_role,
            sender_name=self.role.name,
        )
        conv.add_message(
            content=response_content,
            role=msg_role,
            sender_name=self.role.name,
        )

        if self._verbose:
            print(f"[{self.role.name}]: {response_content[:100]}...")

        return message

    def introduce(self) -> Message:
        """Have the agent introduce themselves.

        Returns:
            Introduction message
        """
        intro = f"Hello! I'm {self.role.name}. {self.role.description}"
        return self.respond(intro)

    def _default_respond(self, context: str, messages: List[Dict]) -> str:
        """Default response generator.

        In a real implementation, this would call an LLM.
        """
        # Simulate a response based on role
        if self.role.agent_type == AgentType.ASSISTANT:
            return f"As {self.role.name}, I'll help with: {context[:50]}..."
        else:
            return f"Hello, I'm {self.role.name}. I'm here to {self.role.description.lower()}"

    def get_conversation(self) -> Conversation:
        """Get the agent's conversation.

        Returns:
            The conversation object
        """
        return self._conversation

    def to_dict(self) -> Dict[str, Any]:
        return {
            "role": self.role.to_dict(),
            "verbose": self._verbose,
        }