"""
Post Understanding Agent.

帖子初理解Agent：分析帖子多模态内容，提取品类、主题、关键词。
"""

from typing import Dict, Any, List
import json
import base64
from pathlib import Path
from urllib.parse import urlparse

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 PostUnderstandingAgent(BaseLLMAgent):
    """帖子初理解Agent

    功能：
    - 综合分析图片视觉风格、文本语义、话题标签
    - 推理帖子的核心主题
    - 提取品类、主题、关键词列表
    """

    def __init__(
        self,
        name: str = "post_understanding_agent",
        description: str = "分析帖子多模态内容，提取品类、主题、关键词",
        model_provider: str = "google_genai",
        temperature: float = 0.1,
        max_tokens: int = 10240
    ):
        system_prompt = """你是一个专业的小红书内容分析专家。你的任务是分析帖子的多模态内容（图片+文本），提取核心信息。

你需要：
1. 综合分析图片的视觉风格、主题、元素
2. 理解标题、正文、话题标签的语义
3. 推理出帖子所属的品类（如：时尚美妆、美食探店、旅游攻略等）
4. 提取帖子的核心主题（一句话概括帖子在讲什么）
5. 提取3-5个关键词

输出格式必须是JSON：
{
    "category": "品类",
    "theme": "核心主题（一句话）",
    "keywords": ["关键词1", "关键词2", "关键词3"]
}

要求：
- 客观准确，不要主观臆测
- 关键词要具体且有代表性
- 品类和主题要简洁明了
"""

        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}
        ]

        # 构建用户消息内容
        message_content = []

        # 添加文本内容
        text_data = state.get("text", {})
        text_prompt = "请分析以下帖子内容：\n\n"

        if text_data.get("title"):
            text_prompt += f"标题：{text_data['title']}\n\n"

        if text_data.get("body"):
            text_prompt += f"正文：{text_data['body']}\n\n"

        if text_data.get("hashtags"):
            hashtags_str = " ".join(text_data["hashtags"])
            text_prompt += f"话题标签：{hashtags_str}\n\n"

        message_content.append({"type": "text", "text": text_prompt})

        # 添加图片内容（多模态）
        images = state.get("images", [])
        if images:
            message_content.append({
                "type": "text",
                "text": f"帖子包含 {len(images)} 张图片，请结合图片内容进行分析："
            })

            for image_path in images:
                try:
                    image_url = self._encode_image(image_path)
                    message_content.append({
                        "type": "image_url",
                        "image_url": {"url": image_url}
                    })
                except Exception as e:
                    logger.warning(f"图片 {image_path} 处理失败: {e}")

        # 添加输出格式要求
        message_content.append({
            "type": "text",
            "text": "\n\n请严格按照JSON格式输出分析结果。"
        })

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

        return messages

    def _encode_image(self, image_path: str) -> str:
        """处理图片URL，对于远程URL直接返回，本地文件转换为base64

        Args:
            image_path: 图片路径或URL

        Returns:
            图片URL（远程URL直接返回，本地文件返回base64 data URL）
        """
        # 判断是否为URL
        parsed = urlparse(image_path)
        is_url = parsed.scheme in ['http', 'https']

        if is_url:
            # Gemini支持直接使用远程URL，无需下载和编码
            logger.info(f"使用远程图片URL: {image_path}")
            return image_path
        else:
            # 本地文件需要转换为base64
            path = Path(image_path)
            if not path.exists():
                raise FileNotFoundError(f"图片文件不存在: {image_path}")

            # 读取图片文件
            with open(path, "rb") as image_file:
                image_data = image_file.read()

            # 根据文件扩展名确定MIME类型
            mime_type = "image/jpeg"
            if path.suffix.lower() in [".png"]:
                mime_type = "image/png"
            elif path.suffix.lower() in [".webp"]:
                mime_type = "image/webp"
            elif path.suffix.lower() in [".gif"]:
                mime_type = "image/gif"

            # 编码为base64
            encoded_string = base64.b64encode(image_data).decode('utf-8')
            logger.info(f"本地图片已编码为base64: {image_path}")
            return f"data:{mime_type};base64,{encoded_string}"

    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（可能被包裹在```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)

            # 验证必需字段
            if "category" not in result or "theme" not in result or "keywords" not in result:
                raise ValueError("响应缺少必需字段")

            # 返回更新后的字段
            return {
                "category": result["category"],
                "theme": result["theme"],
                "keywords": result["keywords"]
            }

        except Exception as e:
            logger.error(f"解析响应失败: {e}，原始内容: {response}")
            # 返回默认值
            return {
                "category": "未知",
                "theme": "无法识别主题",
                "keywords": []
            }
