"""内容生成Agent - 真实调用LLM生成文章"""

import json
import logging
import re
import time
from datetime import datetime, timezone

from app.agent_framework.base import BaseAgent
from app.agent_framework.prompts import CONTENT_GENERATOR_TEMPLATE, TOPIC_SELECTOR_TEMPLATE
from app.agent_framework.protocol import (
    AgentCapability,
    AgentType,
    TaskMessage,
    TaskResult,
    TaskStatus,
)
from app.services.llm import LLMFactory, LLMError

logger = logging.getLogger(__name__)


class ContentGeneratorAgent(BaseAgent):
    """AI内容生成Agent，支持选题和文章生成

    支持的任务类型:
    - generate_topics: 生成选题列表
    - generate_article: 生成完整文章
    """

    def __init__(self):
        super().__init__(
            name="content_generator",
            agent_type=AgentType.CONTENT_GENERATOR,
            version="1.0.0",
        )

    def get_capabilities(self) -> AgentCapability:
        return AgentCapability(
            agent_name=self.name,
            agent_type=self.agent_type,
            version=self.version,
            supported_tasks=["generate_topics", "generate_article"],
            max_concurrency=2,
            description="AI内容生成Agent：支持选题推荐和文章生成，可结合知识库RAG检索",
        )

    async def execute(self, task: TaskMessage) -> TaskResult:
        """执行内容生成任务"""
        started_at = datetime.now(timezone.utc)
        start_time = time.monotonic()

        try:
            task_type = task.task_type
            if task_type == "generate_topics":
                output = await self._generate_topics(task)
            elif task_type == "generate_article":
                output = await self._generate_article(task)
            else:
                raise ValueError(f"Unsupported task type: {task_type}")

            elapsed = time.monotonic() - start_time
            return TaskResult(
                task_id=task.task_id,
                agent_name=self.name,
                status=TaskStatus.COMPLETED,
                output_data=output,
                error_message=None,
                started_at=started_at,
                completed_at=datetime.now(timezone.utc),
                metrics={
                    "elapsed_seconds": round(elapsed, 2),
                    "task_type": task_type,
                },
            )

        except LLMError as e:
            elapsed = time.monotonic() - start_time
            logger.error(f"ContentGenerator LLM error on task {task.task_id}: {e}")
            return TaskResult(
                task_id=task.task_id,
                agent_name=self.name,
                status=TaskStatus.FAILED,
                output_data=None,
                error_message=f"LLM调用失败: {e}",
                started_at=started_at,
                completed_at=datetime.now(timezone.utc),
                metrics={
                    "elapsed_seconds": round(elapsed, 2),
                    "task_type": task.task_type,
                },
            )

        except Exception as e:
            elapsed = time.monotonic() - start_time
            logger.error(f"ContentGenerator task {task.task_id} failed: {e}")
            return TaskResult(
                task_id=task.task_id,
                agent_name=self.name,
                status=TaskStatus.FAILED,
                output_data=None,
                error_message=str(e),
                started_at=started_at,
                completed_at=datetime.now(timezone.utc),
                metrics={
                    "elapsed_seconds": round(elapsed, 2),
                    "task_type": task.task_type,
                },
            )

    async def _generate_topics(self, task: TaskMessage) -> dict:
        """生成选题

        input_data 字段:
        - target_keyword: str
        - brand_name: str (可选)
        - brand_description: str (可选)
        - target_platform: str (默认"通用")
        - knowledge_base_ids: list[str] (可选，用于RAG检索)
        - published_topics: str (可选，已发布选题)
        """
        input_data = task.input_data

        # 上报进度：开始
        await self.report_progress(
            task_id=task.task_id,
            progress=0.1,
            message="开始生成选题...",
        )

        # 1. 如果有knowledge_base_ids，调用RAG检索相关知识
        knowledge_context = await self._retrieve_knowledge(
            input_data.get("knowledge_base_ids", []),
            input_data.get("target_keyword", ""),
        )

        # 上报进度：RAG检索完成
        await self.report_progress(
            task_id=task.task_id,
            progress=0.3,
            message="知识检索完成，开始调用LLM...",
        )

        # 2. 渲染prompt模板
        variables = {
            "target_keyword": input_data.get("target_keyword", ""),
            "brand_name": input_data.get("brand_name", ""),
            "brand_description": input_data.get("brand_description", ""),
            "target_platform": input_data.get("target_platform", "通用"),
            "knowledge_context": knowledge_context,
            "published_topics": input_data.get("published_topics", "暂无"),
        }
        messages = TOPIC_SELECTOR_TEMPLATE.render(variables)

        # 3. 调用LLM
        provider = LLMFactory.get_default()
        response = await provider.chat(messages, temperature=0.8)

        # 上报进度：LLM生成完成
        await self.report_progress(
            task_id=task.task_id,
            progress=0.8,
            message="LLM生成完成，解析输出...",
        )

        # 4. 解析JSON输出
        try:
            topics = json.loads(self._extract_json(response.content))
        except json.JSONDecodeError:
            topics = [{"title": response.content, "reason": "LLM输出解析失败，返回原始内容"}]

        # 上报进度：完成
        await self.report_progress(
            task_id=task.task_id,
            progress=1.0,
            message=f"选题生成完成，共{len(topics) if isinstance(topics, list) else 1}个选题",
        )

        return {
            "topics": topics,
            "usage": response.usage,
        }

    async def _generate_article(self, task: TaskMessage) -> dict:
        """生成文章

        input_data 字段:
        - target_keyword: str
        - brand_name: str (可选)
        - target_platform: str (默认"通用")
        - knowledge_base_ids: list[str] (可选，用于RAG检索)
        - word_count: int (默认2000)
        - content_style: str (默认"专业严谨")
        - content_angle: str (可选)
        - topic_title: str (可选，默认使用target_keyword)
        - model: str (可选，指定LLM模型)
        """
        input_data = task.input_data

        # 上报进度：开始
        await self.report_progress(
            task_id=task.task_id,
            progress=0.1,
            message="开始生成文章...",
        )

        knowledge_context = await self._retrieve_knowledge(
            input_data.get("knowledge_base_ids", []),
            input_data.get("target_keyword", ""),
        )

        # 上报进度：RAG检索完成
        await self.report_progress(
            task_id=task.task_id,
            progress=0.3,
            message="知识检索完成，开始调用LLM...",
        )

        variables = {
            "topic_title": input_data.get("topic_title", input_data.get("target_keyword", "")),
            "target_keyword": input_data.get("target_keyword", ""),
            "target_platform": input_data.get("target_platform", "通用"),
            "content_angle": input_data.get("content_angle", "综合分析"),
            "content_style": input_data.get("content_style", "专业严谨"),
            "word_count": str(input_data.get("word_count", 2000)),
            "brand_name": input_data.get("brand_name", ""),
            "knowledge_context": knowledge_context,
        }
        messages = CONTENT_GENERATOR_TEMPLATE.render(variables)

        # 允许指定模型
        model = input_data.get("model")
        provider = LLMFactory.create(model=model) if model else LLMFactory.get_default()
        word_count = input_data.get("word_count", 2000)
        response = await provider.chat(
            messages,
            temperature=0.7,
            max_tokens=word_count * 2,
        )

        # 上报进度：完成
        await self.report_progress(
            task_id=task.task_id,
            progress=1.0,
            message=f"文章生成完成，字数: {len(response.content)}",
        )

        return {
            "content": response.content,
            "word_count": len(response.content),
            "usage": response.usage,
        }

    async def _retrieve_knowledge(self, kb_ids: list, query: str) -> str:
        """从知识库检索相关内容"""
        if not kb_ids or not query:
            return "暂无相关知识库内容"

        try:
            from app.database import AsyncSessionLocal
            from app.services.knowledge.rag_service import RAGService

            async with AsyncSessionLocal() as session:
                rag = RAGService()
                results = await rag.search(
                    session=session,
                    query=query,
                    knowledge_base_ids=kb_ids,
                    top_k=5,
                )
                if results:
                    return "\n\n---\n\n".join(
                        f"[来源: {r.get('document_title', '未知')}]\n{r.get('content', '')}"
                        for r in results
                    )
        except Exception as e:
            logger.warning(f"RAG检索失败，跳过知识库上下文: {e}")

        return "暂无相关知识库内容"

    def _extract_json(self, text: str) -> str:
        """从LLM响应中提取JSON（可能被markdown包裹）"""
        # 尝试提取```json ... ```中的内容
        match = re.search(r'```(?:json)?\s*\n?(.*?)\n?```', text, re.DOTALL)
        if match:
            return match.group(1).strip()
        # 尝试直接找 [ 或 { 开头的JSON
        for i, c in enumerate(text):
            if c in '[{':
                depth = 0
                for j in range(i, len(text)):
                    if text[j] in '[{':
                        depth += 1
                    elif text[j] in ']}':
                        depth -= 1
                    if depth == 0:
                        return text[i : j + 1]
        return text
