"""
Agent Core - 单智能体核心
"""
import logging
from typing import Optional, List, Dict, Any
from pydantic import BaseModel
from app.agent.memory.manager import MemoryManager
from app.agent.skills.router import SkillRouter
from app.agent.skills.executor import SkillExecutor
from app.agent.llm.factory import LLMFactory

logger = logging.getLogger("agent.core")


class AgentConfig(BaseModel):
    """智能体配置"""
    id: int
    name: str
    role_description: str
    model_provider: str = "openai"
    model_name: str = "gpt-4"
    api_key: Optional[str] = None  # API Key（可选，用于覆盖默认配置）
    base_url: Optional[str] = None  # Base URL（可选，用于覆盖默认配置）
    skills: List[int] = []  # 技能 ID 列表
    knowledge_base_ids: List[int] = []
    timeout: int = 60
    memory_limit: int = 134217728  # 128MB


class AgentResponse(BaseModel):
    """智能体响应"""
    content: str
    tool_calls: List[Dict[str, Any]] = []
    tokens_used: int = 0
    duration_ms: int = 0
    session_id: Optional[str] = None


class AgentCore:
    """单智能体核心类"""

    def __init__(self, config: AgentConfig):
        self.config = config

        # 记录 LLM 初始化信息
        api_key_info = f"{config.api_key[:10]}..." if config.api_key else "None"
        logger.info(f"初始化 AgentCore: name={config.name}, provider={config.model_provider}, model={config.model_name}, api_key={api_key_info}, base_url={config.base_url}")

        self.llm = LLMFactory.create(config.model_provider, config.model_name, config.api_key, config.base_url)
        self.memory = MemoryManager(config.id)
        self.skill_router = SkillRouter(config.skills)
        self.skill_executor = SkillExecutor()

    async def run(self, user_input: str, user_id: int, session_id: str) -> AgentResponse:
        """
        执行智能体对话

        Args:
            user_input: 用户输入
            user_id: 用户 ID
            session_id: 会话 ID

        Returns:
            AgentResponse: 智能体响应
        """
        import time
        start_time = time.time()

        try:
            # 1. 加载记忆
            context = await self.memory.load_context(user_input, user_id, session_id)

            # 2. 构建 Prompt
            prompt = self._build_prompt(user_input, context)

            # 3. LLM 决策
            decision = await self.llm.decide(prompt)

            # 4. 执行技能（如需）
            if decision.get('needs_skill'):
                skill_results = await self._execute_skills(decision.get('tool_calls', []))
                # 5. 基于结果生成回复
                final_response = await self.llm.generate(prompt, skill_results)
            else:
                final_response = decision.get('response', '')

            # 6. 保存记忆
            await self.memory.save(user_input, final_response, user_id, session_id)

            duration_ms = int((time.time() - start_time) * 1000)

            return AgentResponse(
                content=final_response,
                tool_calls=decision.get('tool_calls', []),
                duration_ms=duration_ms,
                session_id=session_id
            )
        except Exception as e:
            duration_ms = int((time.time() - start_time) * 1000)
            return AgentResponse(
                content=f"处理请求时发生错误: {str(e)}",
                duration_ms=duration_ms,
                session_id=session_id
            )

    def _build_prompt(self, user_input: str, context: dict) -> str:
        """构建 Prompt"""
        system_prompt = f"""你是 {self.config.name}。
{self.config.role_description}

相关记忆:
{context.get('summary', '')}

知识库信息:
{context.get('knowledge', '')}

请根据以上上下文回答用户问题，并使用 Markdown 格式输出。"""

        return f"{system_prompt}\n\n用户: {user_input}"

    async def _execute_skills(self, skill_decisions: List[Dict]) -> List[Dict]:
        """执行技能"""
        if not skill_decisions:
            return []

        results = []
        for decision in skill_decisions:
            result = await self.skill_executor.execute(
                skill_id=decision.get('skill_id'),
                params=decision.get('params', {})
            )
            results.append(result)
        return results

    async def run_stream(self, user_input: str, user_id: int, session_id: str):
        """
        执行智能体对话（流式输出）

        优化：对于简单对话，直接流式生成，跳过 decide 步骤（省一次 LLM 调用）
        只有当需要工具时才先判断

        Args:
            user_input: 用户输入
            user_id: 用户 ID
            session_id: 会话 ID

        Yields:
            str: 流式回复片段
        """
        import time
        start_time = time.time()

        try:
            # 1. 加载记忆
            context = await self.memory.load_context(user_input, user_id, session_id)

            # 2. 构建 Prompt
            prompt = self._build_prompt(user_input, context)

            # 3. 直接流式生成回复（跳过 decide，省一次 LLM 调用）
            # 如果将来需要工具能力，可以在这里添加判断逻辑
            async for chunk in self.llm.generate_stream(prompt, []):
                yield chunk

            # 4. 保存记忆（完成后）
            final_response = ""
            await self.memory.save(user_input, final_response, user_id, session_id)

        except Exception as e:
            yield f"处理请求时发生错误: {str(e)}"
