"""Conversation management for CAMEL agents."""

from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from typing import Any, Dict, List, Optional
import uuid


class MessageRole(Enum):
    """Role of message sender."""
    SYSTEM = "system"
    USER = "user"
    ASSISTANT = "assistant"


@dataclass
class Message:
    """A message in the conversation."""
    content: str
    role: MessageRole
    sender_name: str = ""
    message_id: str = field(default_factory=lambda: str(uuid.uuid4())[:8])
    timestamp: datetime = field(default_factory=datetime.now)
    metadata: Dict[str, Any] = field(default_factory=dict)

    def to_dict(self) -> Dict[str, Any]:
        return {
            "message_id": self.message_id,
            "content": self.content,
            "role": self.role.value,
            "sender_name": self.sender_name,
            "timestamp": self.timestamp.isoformat(),
            "metadata": self.metadata,
        }

    def to_openai_format(self) -> Dict[str, str]:
        """Convert to OpenAI message format."""
        return {
            "role": self.role.value,
            "content": self.content,
        }


@dataclass
class Conversation:
    """Manages a conversation between agents."""
    conversation_id: str = field(default_factory=lambda: str(uuid.uuid4())[:8])
    messages: List[Message] = field(default_factory=list)
    max_turns: int = 20
    current_turn: int = 0

    def add_message(
        self,
        content: str,
        role: MessageRole,
        sender_name: str = "",
        metadata: Optional[Dict] = None,
    ) -> Message:
        """Add a message to the conversation.

        Args:
            content: Message content
            role: Role of sender
            sender_name: Name of sender agent
            metadata: Optional metadata

        Returns:
            The created message
        """
        message = Message(
            content=content,
            role=role,
            sender_name=sender_name,
            metadata=metadata or {},
        )
        self.messages.append(message)
        self.current_turn = len(self.messages)
        return message

    def get_messages(self) -> List[Message]:
        """Get all messages."""
        return self.messages.copy()

    def get_openai_messages(self, include_system: bool = True) -> List[Dict[str, str]]:
        """Get messages in OpenAI format.

        Args:
            include_system: Whether to include system messages

        Returns:
            List of messages in OpenAI format
        """
        messages = []
        for msg in self.messages:
            if not include_system and msg.role == MessageRole.SYSTEM:
                continue
            messages.append(msg.to_openai_format())
        return messages

    def get_last_n_messages(self, n: int) -> List[Message]:
        """Get the last n messages.

        Args:
            n: Number of messages to retrieve

        Returns:
            List of recent messages
        """
        return self.messages[-n:] if n < len(self.messages) else self.messages.copy()

    def get_context_string(self, max_messages: int = 10) -> str:
        """Get conversation as context string.

        Args:
            max_messages: Maximum messages to include

        Returns:
            Formatted conversation string
        """
        messages = self.get_last_n_messages(max_messages)
        lines = []
        for msg in messages:
            sender = msg.sender_name or msg.role.value
            lines.append(f"{sender}: {msg.content}")
        return "\n\n".join(lines)

    def is_complete(self) -> bool:
        """Check if conversation has reached max turns.

        Returns:
            True if max turns reached
        """
        return self.current_turn >= self.max_turns

    def clear(self) -> None:
        """Clear all messages."""
        self.messages.clear()
        self.current_turn = 0

    def count_messages(self) -> int:
        """Get total message count.

        Returns:
            Number of messages
        """
        return len(self.messages)

    def to_dict(self) -> Dict[str, Any]:
        return {
            "conversation_id": self.conversation_id,
            "messages": [m.to_dict() for m in self.messages],
            "max_turns": self.max_turns,
            "current_turn": self.current_turn,
        }

    def to_transcript(self) -> str:
        """Export conversation as transcript.

        Returns:
            Human-readable transcript
        """
        lines = [f"=== Conversation {self.conversation_id} ===\n"]
        for msg in self.messages:
            sender = msg.sender_name or msg.role.value.title()
            timestamp = msg.timestamp.strftime("%H:%M:%S")
            lines.append(f"[{timestamp}] {sender}:")
            lines.append(f"{msg.content}")
            lines.append("")
        return "\n".join(lines)