"""AgentPool 单元测试"""

import pytest

from agentkit.core.agent_pool import AgentPool
from agentkit.core.config_driven import AgentConfig
from agentkit.core.protocol import AgentStatus
from agentkit.llm.gateway import LLMGateway
from agentkit.skills.base import Skill, SkillConfig
from agentkit.skills.registry import SkillRegistry
from agentkit.tools.registry import ToolRegistry


@pytest.fixture
def llm_gateway():
    return LLMGateway()


@pytest.fixture
def skill_registry():
    return SkillRegistry()


@pytest.fixture
def tool_registry():
    return ToolRegistry()


@pytest.fixture
def agent_pool(llm_gateway, skill_registry, tool_registry):
    return AgentPool(
        llm_gateway=llm_gateway,
        skill_registry=skill_registry,
        tool_registry=tool_registry,
    )


@pytest.fixture
def sample_agent_config():
    return AgentConfig(
        name="test_agent",
        agent_type="test_type",
        task_mode="llm_generate",
        prompt={"identity": "Test agent", "instructions": "Do test things"},
    )


@pytest.fixture
def sample_skill_config():
    return SkillConfig(
        name="test_skill",
        agent_type="test_skill_type",
        task_mode="llm_generate",
        prompt={"identity": "Test skill agent", "instructions": "Do skill things"},
        intent={"keywords": ["test"], "description": "A test skill"},
    )


class TestAgentPoolCreate:
    """create_agent() 测试"""

    async def test_create_agent_creates_and_starts_agent(
        self, agent_pool, sample_agent_config
    ):
        agent = await agent_pool.create_agent(sample_agent_config)
        assert agent is not None
        assert agent.name == "test_agent"
        assert agent.status == AgentStatus.ONLINE

    async def test_create_agent_stores_in_pool(self, agent_pool, sample_agent_config):
        await agent_pool.create_agent(sample_agent_config)
        retrieved = agent_pool.get_agent("test_agent")
        assert retrieved is not None
        assert retrieved.name == "test_agent"


class TestAgentPoolRemove:
    """remove_agent() 测试"""

    async def test_remove_agent_stops_and_removes(self, agent_pool, sample_agent_config):
        await agent_pool.create_agent(sample_agent_config)
        await agent_pool.remove_agent("test_agent")
        assert agent_pool.get_agent("test_agent") is None

    async def test_remove_nonexistent_agent_no_error(self, agent_pool):
        await agent_pool.remove_agent("nonexistent")  # should not raise


class TestAgentPoolGet:
    """get_agent() 测试"""

    async def test_get_agent_returns_created_agent(
        self, agent_pool, sample_agent_config
    ):
        await agent_pool.create_agent(sample_agent_config)
        agent = agent_pool.get_agent("test_agent")
        assert agent is not None
        assert agent.name == "test_agent"

    async def test_get_agent_nonexistent_returns_none(self, agent_pool):
        result = agent_pool.get_agent("nonexistent")
        assert result is None


class TestAgentPoolList:
    """list_agents() 测试"""

    async def test_list_agents_empty(self, agent_pool):
        result = agent_pool.list_agents()
        assert result == []

    async def test_list_agents_returns_all_info(
        self, agent_pool, sample_agent_config
    ):
        await agent_pool.create_agent(sample_agent_config)
        agents = agent_pool.list_agents()
        assert len(agents) == 1
        assert agents[0]["name"] == "test_agent"
        assert agents[0]["agent_type"] == "test_type"
        assert agents[0]["version"] == "1.0.0"
        assert agents[0]["state"] == AgentStatus.ONLINE.value

    async def test_list_agents_multiple(
        self, agent_pool, sample_agent_config
    ):
        config2 = AgentConfig(
            name="agent2",
            agent_type="type2",
            task_mode="llm_generate",
            prompt={"identity": "Agent 2"},
        )
        await agent_pool.create_agent(sample_agent_config)
        await agent_pool.create_agent(config2)
        agents = agent_pool.list_agents()
        assert len(agents) == 2
        names = {a["name"] for a in agents}
        assert names == {"test_agent", "agent2"}


class TestAgentPoolCreateFromSkill:
    """create_agent_from_skill() 测试"""

    async def test_create_agent_from_skill(
        self, agent_pool, skill_registry, sample_skill_config
    ):
        skill = Skill(config=sample_skill_config)
        skill_registry.register(skill)
        agent = await agent_pool.create_agent_from_skill("test_skill")
        assert agent is not None
        assert agent.name == "test_skill"
        assert agent_pool.get_agent("test_skill") is not None

    async def test_create_agent_from_skill_not_found(self, agent_pool):
        with pytest.raises(Exception):
            await agent_pool.create_agent_from_skill("nonexistent_skill")


class TestAgentPoolDuplicate:
    """重复名称测试"""

    async def test_duplicate_name_overwrites_old_instance(
        self, agent_pool, sample_agent_config
    ):
        await agent_pool.create_agent(sample_agent_config)
        # Create again with same name
        await agent_pool.create_agent(sample_agent_config)
        agents = agent_pool.list_agents()
        assert len(agents) == 1
        assert agents[0]["name"] == "test_agent"
