"""Server E2E 集成测试 - 完整流程"""

import pytest
from unittest.mock import AsyncMock
from fastapi.testclient import TestClient

from agentkit.core.protocol import AgentStatus
from agentkit.llm.gateway import LLMGateway
from agentkit.llm.protocol import LLMProvider, LLMRequest, LLMResponse, TokenUsage
from agentkit.skills.base import Skill, SkillConfig
from agentkit.skills.registry import SkillRegistry
from agentkit.tools.registry import ToolRegistry
from agentkit.server.app import create_app


class MockLLMProvider(LLMProvider):
    """Mock LLM Provider for integration tests"""

    def __init__(self):
        self.call_count = 0

    async def chat(self, request: LLMRequest) -> LLMResponse:
        self.call_count += 1
        return LLMResponse(
            content='{"result": "integration test output", "content": "This is the generated content from the skill"}',
            model="mock-model",
            usage=TokenUsage(prompt_tokens=50, completion_tokens=100),
        )


@pytest.fixture
def llm_gateway():
    gw = LLMGateway()
    gw.register_provider("mock", MockLLMProvider())
    return gw


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


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


@pytest.fixture
def app(llm_gateway, skill_registry, tool_registry):
    return create_app(
        llm_gateway=llm_gateway,
        skill_registry=skill_registry,
        tool_registry=tool_registry,
    )


@pytest.fixture
def client(app):
    return TestClient(app)


class TestFullFlow:
    """完整流程：register skill → create agent → submit task → get result"""

    def test_register_skill_create_agent_submit_task(self, client):
        # Step 1: Register a skill
        skill_response = client.post(
            "/api/v1/skills",
            json={
                "config": {
                    "name": "content_writer",
                    "agent_type": "content_generation",
                    "task_mode": "llm_generate",
                    "description": "Content writing skill",
                    "prompt": {
                        "identity": "You are a content writer",
                        "instructions": "Write high-quality content",
                        "output_format": "JSON",
                    },
                    "intent": {
                        "keywords": ["write", "content", "article"],
                        "description": "Content writing and generation",
                    },
                    "quality_gate": {
                        "required_fields": ["content"],
                        "min_word_count": 5,
                    },
                }
            },
        )
        assert skill_response.status_code == 201

        # Step 2: Create agent from skill
        agent_response = client.post(
            "/api/v1/agents",
            json={"skill_name": "content_writer"},
        )
        assert agent_response.status_code == 201
        agent_data = agent_response.json()
        assert agent_data["name"] == "content_writer"

        # Step 3: Verify agent is listed
        list_response = client.get("/api/v1/agents")
        assert list_response.status_code == 200
        agents = list_response.json()
        assert len(agents) == 1
        assert agents[0]["name"] == "content_writer"

        # Step 4: Submit task using skill_name
        task_response = client.post(
            "/api/v1/tasks",
            json={
                "input_data": {"query": "Write an article about AI"},
                "skill_name": "content_writer",
            },
        )
        assert task_response.status_code == 200
        task_data = task_response.json()
        # Result should contain standardized output
        assert "skill_name" in task_data or "data" in task_data or "output" in task_data

        # Step 5: Verify skill is listed
        skills_response = client.get("/api/v1/skills")
        assert skills_response.status_code == 200
        skills = skills_response.json()
        assert len(skills) >= 1

    def test_submit_task_auto_routes_to_skill(self, client):
        """Intent Router 自动路由到正确的 skill"""
        # Register two skills with different keywords
        client.post(
            "/api/v1/skills",
            json={
                "config": {
                    "name": "translator",
                    "agent_type": "translation",
                    "task_mode": "llm_generate",
                    "prompt": {"identity": "Translator", "instructions": "Translate text"},
                    "intent": {
                        "keywords": ["translate", "翻译"],
                        "description": "Translation skill",
                    },
                }
            },
        )
        client.post(
            "/api/v1/skills",
            json={
                "config": {
                    "name": "summarizer",
                    "agent_type": "summarization",
                    "task_mode": "llm_generate",
                    "prompt": {"identity": "Summarizer", "instructions": "Summarize text"},
                    "intent": {
                        "keywords": ["summarize", "摘要"],
                        "description": "Summarization skill",
                    },
                }
            },
        )

        # Submit task with keyword matching "translate"
        response = client.post(
            "/api/v1/tasks",
            json={
                "input_data": {"query": "Please translate this text to English"},
            },
        )
        # Should route to translator skill via keyword matching
        assert response.status_code == 200

    def test_delete_agent_then_submit_task_error(self, client):
        """Delete agent → submit task → appropriate error"""
        # Register skill and create agent
        client.post(
            "/api/v1/skills",
            json={
                "config": {
                    "name": "deletable_skill",
                    "agent_type": "deletable_type",
                    "task_mode": "llm_generate",
                    "prompt": {"identity": "Deletable"},
                    "intent": {"keywords": ["delete"], "description": "Deletable skill"},
                }
            },
        )
        client.post(
            "/api/v1/agents",
            json={"skill_name": "deletable_skill"},
        )

        # Delete the agent
        delete_response = client.delete("/api/v1/agents/deletable_skill")
        assert delete_response.status_code == 204

        # Submit task referencing deleted agent
        task_response = client.post(
            "/api/v1/tasks",
            json={
                "input_data": {"query": "test"},
                "agent_name": "deletable_skill",
            },
        )
        # Should return 404 since agent was deleted
        assert task_response.status_code == 404

    def test_health_check_in_flow(self, client):
        """Health check works during full flow"""
        response = client.get("/api/v1/health")
        assert response.status_code == 200
        data = response.json()
        assert data["status"] in ("ok", "healthy")

    def test_llm_usage_after_tasks(self, client):
        """LLM usage stats available after task execution"""
        # Register skill and submit a task
        client.post(
            "/api/v1/skills",
            json={
                "config": {
                    "name": "usage_skill",
                    "agent_type": "usage_type",
                    "task_mode": "llm_generate",
                    "prompt": {"identity": "Usage Skill"},
                    "intent": {"keywords": ["usage"], "description": "Usage skill"},
                }
            },
        )
        client.post(
            "/api/v1/tasks",
            json={
                "input_data": {"query": "test usage"},
                "skill_name": "usage_skill",
            },
        )

        # Check usage
        response = client.get("/api/v1/llm/usage")
        assert response.status_code == 200
