"""
Post Summary Deconstruction Agent.

帖子整体解构Agent：解构帖子整体的各种描述维度。
"""

from typing import Dict, Any, List
import json

from src.components.agents.base import BaseLLMAgent
from src.states.what_deconstruction_state import WhatDeconstructionState
from src.utils.logger import get_logger

logger = get_logger(__name__)


class PostSummaryDeconstructionAgent(BaseLLMAgent):
    """帖子整体解构Agent

    根据 PRD 1.4 - 2.2.2.2 帖子整体节点要求：

    **核心功能**：
    1. 综合所有子元素的解构结果（图片、文本）
    2. 从多个描述维度解构帖子整体
    3. 帖子总体的各种描述、总结、归纳等维度或角度，每一个维度都是一个字段项

    **必须满足的约束条件**：
    1. 维度名称和数量根据每篇帖子动态变化
    2. **一定要包含本帖子最关键/最吸引内容消费者的亮点维度**
       - 包括但不限于：内容亮点、情绪共鸣点、创作手法等维度
    3. **描述维度的数量不得少于3个**
       - 要尽可能多而全的覆盖这个帖子的所有可描述角度
    4. 包括但不限于：品类、主题、脚本等维度
    5. 描述维度应根据帖子的品类、主题、关键词等信息来向知识库动态请求询问
    """

    def __init__(
        self,
        name: str = "post_summary_deconstruction_agent",
        description: str = "解构帖子整体的各种描述维度",
        model_provider: str = "google_genai",
        temperature: float = 0.1,
        max_tokens: int = 10240
    ):
        system_prompt = """你是一个专业的内容分析专家。你的任务是从多个维度解构帖子整体。

根据 PRD 1.4 - 2.2.2.2 帖子整体节点要求：

**核心任务**：
1. 综合分析所有子元素（图片、文本）的解构结果
2. 从多个描述维度解构帖子整体
3. 帖子总体的各种描述、总结、归纳等维度或角度，每一个维度都是一个字段项

**必须满足的约束条件**：
1. ✅ 维度名称和数量根据每篇帖子动态变化
2. ✅ **一定要包含本帖子最关键/最吸引内容消费者的亮点维度**
   - 包括但不限于：内容亮点、情绪共鸣点、创作手法等维度
3. ✅ **描述维度的数量不得少于3个**
   - 要尽可能多而全的覆盖这个帖子的所有可描述角度
4. ✅ 包括但不限于：品类、主题、脚本等维度
5. ✅ 描述维度应根据帖子的品类、主题、关键词等信息来向知识库动态请求询问
   - Query句式（参见 PRD 1.4 - 3.2）：
     对于一篇主题为"{帖子主题}"，品类为"{帖子品类}"，关键词包含"{帖子关键词列表}"的多模态社交媒体帖子，
     从内容创作者视角进行What要素的初步识别和分类，需要使用哪些通用工具？

**输出格式必须是JSON**：
{
    "品类": "值",
    "主题": "值",
    "脚本": "值",
    "内容亮点": "值",           # 必须包含
    "情绪共鸣点": "值",         # 必须包含
    "创作手法": "值",           # 必须包含
    "整体风格": "值",
    "视觉呈现": "值",
    "内容价值": "值",
    "目标受众": "值",
    ... # 其他动态维度（根据帖子特点）
}

**输出要求**：
1. ✅ 客观准确，严格基于实际解构结果，禁止主观臆测、凭空假设、虚构数据
2. ✅ 维度名称和数量根据帖子内容动态确定
3. ✅ 突出核心特征和亮点
4. ✅ **最少包含3个描述维度**
5. ✅ 必须包含"内容亮点"、"情绪共鸣点"、"创作手法"等吸引消费者的亮点维度
"""

        super().__init__(
            name=name,
            description=description,
            model_provider=model_provider,
            system_prompt=system_prompt,
            temperature=temperature,
            max_tokens=max_tokens
        )

    def _build_messages(self, state: WhatDeconstructionState) -> List[Dict[str, Any]]:
        """构建消息

        包含所有子元素解构结果、消费者亮点、总结维度
        """
        messages = [
            {"role": "system", "content": self.system_prompt}
        ]

        # 构建用户消息
        user_prompt = "# 帖子解构结果\n\n"

        # 添加帖子基本信息
        category = state.get("category", "未知")
        theme = state.get("theme", "未知")
        keywords = state.get("keywords", [])

        user_prompt += f"**品类**：{category}\n"
        user_prompt += f"**主题**：{theme}\n"
        user_prompt += f"**关键词**：{', '.join(keywords)}\n\n"

        # 添加图片解构结果
        image_results = state.get("image_deconstruction_results", [])
        if image_results:
            user_prompt += "## 图片元素解构\n\n"
            for idx, img_result in enumerate(image_results, 1):
                what = img_result.get("what", "")
                desc = img_result.get("description", img_result.get("描述", {}))
                user_prompt += f"### 图片 {idx}\n"
                user_prompt += f"**What**: {what}\n"
                user_prompt += f"**描述**: {json.dumps(desc, ensure_ascii=False, indent=2)}\n\n"

        # 添加文本解构结果
        text_results = state.get("text_deconstruction_results", [])
        if text_results:
            user_prompt += "## 文本元素解构\n\n"
            for idx, text_result in enumerate(text_results, 1):
                what = text_result.get("what", "")
                desc = text_result.get("description", text_result.get("描述", {}))
                user_prompt += f"### 文本元素 {idx}\n"
                user_prompt += f"**What**: {what}...\n"  # 限制长度
                user_prompt += f"**描述**: {json.dumps(desc, ensure_ascii=False, indent=2)}\n\n"

        # 添加消费者亮点
        consumer_highlights = state.get("consumer_highlights", [])
        if consumer_highlights:
            user_prompt += "## 消费者关注的亮点\n\n"
            for idx, highlight in enumerate(consumer_highlights, 1):
                element = highlight.get("element", "")
                highlight_desc = highlight.get("highlight", "")
                emotion = highlight.get("emotion", "")
                user_prompt += f"{idx}. **{element}**: {highlight_desc} ({emotion})\n"
            user_prompt += "\n"

        # 添加总结维度要求
        # 根据 PRD 1.4 - 2.2.2.2：
        # - 描述维度有哪些、有多少个，需要根据本帖子的品类、主题、关键词等信息来向知识库动态请求询问
        # - Query句式：参见3.2 环节中对query的定义
        # 这里使用默认维度作为示例（实际应从知识库获取）
        summary_dimensions = state.get("summary_dimensions", [
            "品类",
            "主题",
            "脚本",
            "内容亮点",
            "情绪共鸣点",
            "创作手法",
            "整体风格",
            "视觉呈现",
            "内容价值",
            "目标受众"
        ])

        user_prompt += "## 解构维度\n\n"
        user_prompt += "请根据以下维度进行帖子整体解构（至少包含3个维度）：\n"
        for dim in summary_dimensions:
            user_prompt += f"- {dim}\n"

        user_prompt += "\n请严格按照JSON格式输出，字段名为上述维度名。至少包含3个描述维度。"

        messages.append({"role": "user", "content": user_prompt})

        return messages

    def _update_state(self, state: WhatDeconstructionState, response: Any) -> Dict[str, Any]:
        """更新状态

        解析LLM返回的JSON，更新帖子整体
        """
        try:
            # 提取响应内容
            if hasattr(response, 'content'):
                content = response.content
            else:
                content = str(response)

            # 尝试提取JSON
            content = content.strip()
            if "```json" in content:
                content = content.split("```json")[1].split("```")[0].strip()
            elif "```" in content:
                content = content.split("```")[1].split("```")[0].strip()

            # 解析JSON
            result = json.loads(content)

            # 返回更新后的字段
            return {
                "post_overall": result  # 更新为 post_overall
            }

        except Exception as e:
            logger.error(f"解析帖子整体响应失败: {e}，原始内容: {response}")
            # 返回默认值
            return {
                "post_overall": {
                    "错误": f"解析失败: {str(e)}"
                }
            }
