"""
Unit tests for the Agent class.
"""

import pytest
from synqed import Agent
from a2a.types import AgentCard


class TestAgent:
    """Tests for the Agent class."""
    
    def test_agent_creation_with_simple_skills(self):
        """Test creating an agent with simple string skills."""
        agent = Agent(
            name="Test Agent",
            description="A test agent",
            skills=["skill1", "skill2", "skill3"]
        )
        
        assert agent.name == "Test Agent"
        assert agent.description == "A test agent"
        assert agent.version == "1.0.0"
        assert len(agent._skills_config) == 3
    
    def test_agent_creation_with_detailed_skills(self):
        """Test creating an agent with detailed skill dictionaries."""
        skills = [
            {
                "skill_id": "cooking",
                "name": "Cooking",
                "description": "Cook recipes",
                "tags": ["food", "recipes"]
            }
        ]
        
        agent = Agent(
            name="Chef Agent",
            description="A cooking agent",
            skills=skills
        )
        
        assert agent.name == "Chef Agent"
        assert len(agent._skills_config) == 1
    
    def test_agent_card_generation(self):
        """Test that agent card is generated correctly."""
        agent = Agent(
            name="Test Agent",
            description="Test description",
            skills=["skill1"]
        )
        
        card = agent.card
        
        assert isinstance(card, AgentCard)
        assert card.name == "Test Agent"
        assert card.description == "Test description"
        assert len(card.skills) == 1
        assert card.skills[0].id == "skill1"
    
    def test_agent_url_update(self):
        """Test updating agent URL."""
        agent = Agent(
            name="Test Agent",
            description="Test",
            skills=["skill1"]
        )
        
        new_url = "http://newhost:9000/a2a/v1"
        agent.set_url(new_url)
        
        assert agent.url == new_url
        assert agent.card.url == new_url
    
    def test_agent_with_custom_executor(self):
        """Test agent with custom executor function."""
        async def custom_executor(context):
            return "Custom response"
        
        agent = Agent(
            name="Custom Agent",
            description="Has custom executor",
            skills=["custom"],
            executor=custom_executor
        )
        
        executor = agent.get_executor()
        assert executor is not None
    
    def test_agent_default_executor(self):
        """Test that agent creates default executor when none provided."""
        agent = Agent(
            name="Default Agent",
            description="Uses default executor",
            skills=["default"]
        )
        
        executor = agent.get_executor()
        assert executor is not None
    
    def test_agent_set_executor(self):
        """Test setting executor after agent creation."""
        agent = Agent(
            name="Test Agent",
            description="Test",
            skills=["test"]
        )
        
        async def new_executor(context):
            return "New response"
        
        agent.set_executor(new_executor)
        executor = agent.get_executor()
        
        assert executor is not None
    
    def test_agent_with_capabilities(self):
        """Test agent with custom capabilities."""
        agent = Agent(
            name="Advanced Agent",
            description="Has capabilities",
            skills=["skill1"],
            capabilities={
                "streaming": True,
                "push_notifications": True
            }
        )
        
        card = agent.card
        assert card.capabilities.streaming is True
        assert card.capabilities.push_notifications is True
    
    def test_agent_with_custom_modes(self):
        """Test agent with custom input/output modes."""
        agent = Agent(
            name="Custom Mode Agent",
            description="Custom modes",
            skills=["skill1"],
            default_input_modes=["application/json"],
            default_output_modes=["text/html"]
        )
        
        card = agent.card
        assert "application/json" in card.default_input_modes
        assert "text/html" in card.default_output_modes
    
    def test_agent_repr(self):
        """Test agent string representation."""
        agent = Agent(
            name="Test Agent",
            description="Test",
            skills=["skill1", "skill2"]
        )
        
        repr_str = repr(agent)
        assert "Test Agent" in repr_str
        assert "skills=2" in repr_str
    
    @pytest.mark.asyncio
    async def test_agent_executor_returns_string(self, simple_agent):
        """Test that agent executor properly handles string responses."""
        import uuid
        from a2a.types import Task, TaskStatus, TaskState, Message, Part, TextPart, Role
        from a2a.server.agent_execution import RequestContext
        
        # Create a user message
        user_message = Message(
            role=Role.user,
            parts=[Part(root=TextPart(text="Test message"))],
            message_id=str(uuid.uuid4()),
            task_id="test-task-id",
            context_id="test-context",
        )
        
        # Create MessageSendParams
        from a2a.types import MessageSendParams
        params = MessageSendParams(message=user_message)
        
        # Create a mock context
        task = Task(
            id="test-task-id",
            context_id="test-context",
            status=TaskStatus(state=TaskState.submitted),
            history=[user_message]
        )
        
        context = RequestContext(
            request=params,
            task_id="test-task-id",
            context_id="test-context",
            task=task
        )
        
        # Create an event queue to capture the result
        from a2a.server.events import EventQueue
        queue = EventQueue()
        
        executor = simple_agent.get_executor()
        await executor.execute(context, queue)
        
        # Get the result from the queue
        result = await queue.dequeue_event()
        
        # Should return a Message object
        assert hasattr(result, 'parts')
        assert hasattr(result, 'role')
        assert result.role == Role.agent

