#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
脚本正交分析Agent

功能: 将脚本元素和段落进行正交分析，生成二维矩阵表格
输出: 正交分析矩阵（段落 × 元素维度）
"""

from typing import List
from src.components.agents.base import BaseLLMAgent
from src.utils.logger import get_logger
from src.utils.llm_invoker import LLMInvoker

logger = get_logger(__name__)


class ScriptOrthogonalAnalysisAgent(BaseLLMAgent):
    """脚本正交分析Agent - 将元素和段落进行正交分析生成矩阵表格
    """

    def __init__(
        self,
        name: str = "script_orthogonal_analysis_agent",
        description: str = "脚本正交分析Agent - 将元素和段落进行正交分析生成矩阵表格",
        model_provider: str = "google_genai",
        temperature: float = 0.1,
        max_tokens: int = 40960
    ):
        """初始化脚本正交分析Agent
        """
        system_prompt = self._build_system_prompt()
        super().__init__(
            name=name,
            description=description,
            model_provider=model_provider,
            system_prompt=system_prompt,
            temperature=temperature,
            max_tokens=max_tokens
        )

    def _build_system_prompt(self) -> str:
        """构建系统提示词"""
        return """你是脚本正交分析专家，擅长将脚本元素和段落进行二维矩阵分析。

# 核心能力
1. 矩阵生成：将段落作为行，元素作为列，生成正交分析矩阵
2. 细粒度分析：针对每个段落×元素的交叉点，分析该元素在该段落中的具体表现
3. 结构化输出：生成清晰的二维表格结构

# 工作原则
- 全面覆盖：覆盖所有段落和所有元素维度
- 精准分析：每个交叉点都要有明确的分析结论
- 留空规则：如果某元素在某段落中不存在或不明显，填写空字符串"""

    def process(self, state: dict) -> dict:
        """处理state，执行正交分析

        从state中提取所需数据，执行正交分析，并返回结果

        Args:
            state: 工作流状态，包含:
                - text: 文本数据 {title, body}
                - images: 图片URL列表
                - script_sections: 段落列表（来自script_section_division_agent）
                - script_elements: 元素列表（来自script_element_extraction_agent）

        Returns:
            dict: 包含正交分析矩阵
        """
        if not self.is_initialized:
            self.initialize()

        logger.info("=== 开始脚本正交分析 ===")

        # 从state中提取数据
        text_data = state.get("text", {})
        images = state.get("images", [])
        script_sections = state.get("script_sections", {})
        script_elements = state.get("script_elements", {})

        # 执行正交分析
        logger.info("执行正交分析")
        result = self._orthogonal_analysis(
            text_data=text_data,
            images=images,
            script_sections=script_sections,
            script_elements=script_elements
        )

        # 只打印JSON结构
        import json
        logger.info(f"正交分析结果:\n{json.dumps(result, ensure_ascii=False, indent=2)}")

        return result

    def _extract_leaf_sections(self, sections: List[dict], parent_desc: str = "") -> List[dict]:
        """递归提取叶子段落（最底层段落）

        Args:
            sections: 段落列表（可能包含嵌套）
            parent_desc: 父级描述（用于构建完整路径）

        Returns:
            List[dict]: 叶子段落列表，每个包含 {"路径": "父级>子级", "内容范围": [...]}
        """
        leaf_sections = []

        for section in sections:
            section_desc = section.get("描述", "")
            full_path = f"{parent_desc} > {section_desc}" if parent_desc else section_desc

            children = section.get("子项", [])

            if children:
                # 有子项，递归处理
                leaf_sections.extend(self._extract_leaf_sections(children, full_path))
            else:
                # 叶子节点
                leaf_sections.append({
                    "路径": full_path,
                    "内容范围": section.get("内容范围", [])
                })

        return leaf_sections

    def _extract_element_types(self, elements: List[dict]) -> List[dict]:
        """提取元素类型（第1层元素作为类型）

        Args:
            elements: 元素列表（可能包含嵌套）

        Returns:
            List[dict]: 元素类型列表，每个包含 {"类型名称": "...", "描述": "...", "子元素": [...]}
        """
        element_types = []

        for element in elements:
            element_name = element.get("元素名称", "")
            element_desc = element.get("描述", "")
            children = element.get("子项", [])

            if element_name:
                element_types.append({
                    "类型名称": element_name,
                    "描述": element_desc,
                    "子元素": children
                })

        return element_types

    def _orthogonal_analysis(self, text_data: dict, images: List[str],
                            script_sections: dict, script_elements: dict) -> dict:
        """正交分析
        将段落和元素类型进行二维矩阵分析
        """
        logger.info("【正交分析】生成段落×元素类型矩阵")

        # 提取段落和元素
        sections_list = script_sections.get("段落列表", [])
        elements_list = script_elements.get("元素列表", [])

        # 提取叶子段落
        leaf_sections = self._extract_leaf_sections(sections_list)
        logger.info(f"提取到 {len(leaf_sections)} 个叶子段落")

        # 提取元素类型（第1层）
        element_types = self._extract_element_types(elements_list)
        logger.info(f"提取到 {len(element_types)} 个元素类型")

        # 构建帖子内容
        post_content_parts = []
        if text_data.get("title"):
            post_content_parts.append(f"标题: {text_data['title']}")
        if text_data.get("body"):
            post_content_parts.append(f"正文: {text_data['body']}")

        post_content = "\n".join(post_content_parts) if post_content_parts else "无文本信息"

        # 构建段落信息
        sections_info = ""
        for idx, section in enumerate(leaf_sections, 1):
            sections_info += f"\n{idx}. {section['路径']}"
            sections_info += f"\n   内容范围: {section['内容范围']}"

        # 构建元素类型信息（包含子元素）
        elements_info = ""
        for idx, elem_type in enumerate(element_types, 1):
            elements_info += f"\n{idx}. **{elem_type['类型名称']}**: {elem_type['描述']}"
            if elem_type['子元素']:
                elements_info += "\n   包含子元素:"
                for child in elem_type['子元素']:
                    child_name = child.get('元素名称', '')
                    child_desc = child.get('描述', '')
                    elements_info += f"\n   - {child_name}: {child_desc}"

        # 提取元素类型名称列表
        element_type_names = [et['类型名称'] for et in element_types]

        # 构建prompt
        prompt = f"""# 帖子内容

{post_content}

# 段落列表（叶子段落）
{sections_info}

# 元素类型列表（第1层分类）
{elements_info}

# 任务

对每个**段落×元素类型**的交叉点进行分析，生成正交矩阵表格。

## 分析原则

1. **全面覆盖**：覆盖所有段落和所有元素类型
2. **精准分析**：针对每个交叉点，分析该元素类型在该段落中的具体表现
3. **类型层面分析**：分析时要考虑该元素类型下的所有子元素
4. **留空规则**：
   - 如果该元素类型在该段落中**不存在**或**不明显**，填写空字符串 ""
   - 如果该元素类型在该段落中**存在且明显**，填写具体表现描述（可以综合该类型下的多个子元素）

## 元素类型说明

每个元素类型都代表一个抽象维度，包含多个具体子元素。
分析时需要：
- 识别该类型下哪些子元素在段落中出现
- 综合描述该类型在段落中的整体表现
- 如果该类型下的子元素都不存在，则留空

## 输出要求

- **矩阵结构**：段落×元素类型的二维表格
- **行**：每一行代表一个段落
- **列**：每一列代表一个元素类型（第1层分类）
- **交叉点值**：该元素类型在该段落中的具体表现（不存在则为空字符串）

# 输出（JSON）

{{
  "正交矩阵": [
    {{
      "段落": "段落路径",
      "内容范围": ["图1", "正文——具体文字内容片段"],
      "元素类型分析": {{
        "元素类型1": "该类型在此段落的具体表现（综合该类型下所有子元素的表现）",
        "元素类型2": "该类型在此段落的具体表现",
        "元素类型3": "",
        ...
      }}
    }}
  ],
  "元素类型列表": ["元素类型1", "元素类型2", "元素类型3", ...]
}}

**示例输出**：

{{
  "正交矩阵": [
    {{
      "段落": "开头 > 引入场景",
      "内容范围": ["图1", "正文——早晨的阳光洒进房间"],
      "元素类型分析": {{
        "核心主题与现象": "展现日常生活场景，为后续主题奠定基础",
        "内容对象与状态": "女主角小美刚醒来，处于放松的原始状态",
        "内容呈现形式": "采用温馨的视觉风格，配以旁白文字",
        "传播目标与效果": "引起观众的代入感，营造轻松的氛围"
      }}
    }},
    {{
      "段落": "过程 > 遇到问题",
      "内容范围": ["图2", "图3", "正文——突然发现钥匙不见了"],
      "元素类型分析": {{
        "核心主题与现象": "揭示冲突点，推动故事发展",
        "内容对象与状态": "女主角处于焦虑状态，钥匙丢失成为核心问题",
        "内容呈现形式": "采用紧张的镜头语言和对白，强化情绪",
        "传播目标与效果": "制造悬念，引发观众的情绪共鸣"
      }}
    }}
  ],
  "元素类型列表": ["核心主题与现象", "内容对象与状态", "内容呈现形式", "传播目标与效果"]
}}"""

        # 构建多模态消息
        message_content = [{"type": "text", "text": prompt}]

        # 添加图片
        if images:
            for idx, image_url in enumerate(images, 1):
                message_content.append({"type": "text", "text": f"[图片{idx}]"})
                message_content.append({
                    "type": "image_url",
                    "image_url": {"url": image_url}
                })

        messages = [
            {"role": "system", "content": self.system_prompt},
            {"role": "user", "content": message_content}
        ]

        # 调用LLM
        result = LLMInvoker.safe_invoke(
            self,
            "正交分析",
            messages,
            fallback={"正交矩阵": [], "元素类型列表": []}
        )

        # 只打印JSON结构
        import json
        logger.info(f"正交分析详细结果:\n{json.dumps(result, ensure_ascii=False, indent=2)}")

        return result

    def _build_messages(self, state: dict) -> List[dict]:
        """构建消息 - ScriptOrthogonalAnalysisAgent 不使用此方法

        本 Agent 使用 _orthogonal_analysis 方法直接构建消息
        """
        return []

    def _update_state(self, state: dict, response) -> dict:
        """更新状态 - ScriptOrthogonalAnalysisAgent 不使用此方法

        本 Agent 使用 _orthogonal_analysis 方法直接返回结果
        """
        return state
