#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
内容过滤Agent

功能：过滤bodytext中与帖子主内容不相关的话题标签，返回过滤后的bodytext
"""

from typing import Any, Dict, List
import re

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 ContentFilterAgent(BaseLLMAgent):
    """内容过滤Agent - 过滤bodytext中不相关的话题标签

    职责：
    - 分析帖子的主要内容（图片、标题、正文bodytext）
    - 识别bodytext中的话题标签
    - 判断每个话题标签是否与主内容相关
    - 移除不相关的标签，返回过滤后的bodytext
    """

    def __init__(
        self,
        name: str = "content_filter_agent",
        description: str = "内容过滤Agent - 过滤bodytext中不相关的话题标签",
        model_provider: str = "google_genai",
        temperature: float = 0.1,
        max_tokens: int = 20480
    ):
        """初始化内容过滤Agent

        Args:
            name: Agent名称
            description: Agent描述
            model_provider: 模型提供商
            temperature: 生成温度（较低以确保准确判断）
            max_tokens: 最大token数
        """
        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 """你是内容过滤专家，从bodytext中识别并移除与帖子主内容不相关的话题标签。

# 核心原则

1. **显性匹配**：标签必须直接描述帖子中明确展示的内容（不能基于隐喻、联想、推理）
2. **主题相关**：标签必须与帖子核心主题有关（而非仅描述表现形式）
3. **严格过滤**：有疑问时倾向于移除

# 判断方法

对每个标签进行双重验证，两项都通过才保留：

**A. 显性匹配检查**
- 标签描述的主体与帖子展示的主体字面意义一致？
- 不需要任何推理就能直接证明标签？
- 避免使用"体现"、"符合"、"象征"、"代表"、"反映"等推理词汇

**B. 主题相关性检查**
- 标签描述的是主题内容本身（讲什么、做什么、说什么）？
- 还是仅描述表现形式（呈现方式、风格、格式）？
- 主题内容 → 相关；仅表现形式 → 不相关

**最终判断**：A通过 且 B通过 → 保留；否则 → 移除

# 输出要求

从bodytext移除不相关标签，保持其他内容和格式不变，给出简洁明确的理由。"""

    def process(self, state: Dict[str, Any], config=None) -> Dict[str, Any]:
        """处理状态 - 过滤bodytext中的话题标签

        输入state包含：
        - text: {title, body}
        - images: 图片URL列表

        输出：
        {
            "filtered_body": "过滤后的bodytext",
            "original_body": "原始bodytext",
            "removed_hashtags": ["被移除的标签1", "被移除的标签2", ...],
            "kept_hashtags": ["保留的标签1", "保留的标签2", ...],
            "filter_details": [
                {
                    "hashtag": "标签",
                    "is_relevant": true/false,
                    "reason": "判断理由"
                },
                ...
            ]
        }
        """
        if not self.is_initialized:
            self.initialize()

        logger.info("=" * 80)
        logger.info("内容过滤 (ContentFilterAgent)")
        logger.info("=" * 80)

        try:
            text_data = state.get("text", {})
            images = state.get("images", [])

            # 获取原始bodytext
            original_body = text_data.get("body", "")

            if not original_body:
                logger.info("无bodytext内容，跳过过滤")
                return {
                    "filtered_body": "",
                    "original_body": "",
                    "removed_hashtags": [],
                    "kept_hashtags": [],
                    "filter_details": []
                }

            logger.info(f"原始bodytext长度: {len(original_body)}")

            # 提取bodytext中的所有标签
            hashtags = self._extract_hashtags(original_body)
            logger.info(f"检测到 {len(hashtags)} 个标签: {hashtags}")

            if not hashtags:
                logger.info("bodytext中未检测到标签，无需过滤")
                return {
                    "filtered_body": original_body,
                    "original_body": original_body,
                    "removed_hashtags": [],
                    "kept_hashtags": [],
                    "filter_details": []
                }

            # 调用LLM进行标签过滤
            filter_result = self._filter_content(
                text_data,
                images,
                original_body,
                hashtags
            )

            # 提取过滤后的bodytext
            filtered_body = filter_result.get("filtered_body", original_body)
            filter_details = filter_result.get("filter_details", [])

            # 统计被保留和移除的标签
            kept_hashtags = [
                detail["hashtag"]
                for detail in filter_details
                if detail.get("is_relevant", False)
            ]
            removed_hashtags = [
                detail["hashtag"]
                for detail in filter_details
                if not detail.get("is_relevant", False)
            ]

            logger.info(f"过滤后bodytext长度: {len(filtered_body)}")
            logger.info(f"保留的标签 ({len(kept_hashtags)}): {kept_hashtags}")
            logger.info(f"移除的标签 ({len(removed_hashtags)}): {removed_hashtags}")

            # 输出详细过滤结果
            if filter_details:
                logger.info("\n过滤详情:")
                for detail in filter_details:
                    status = "✓ 保留" if detail.get("is_relevant") else "✗ 移除"
                    logger.info(f"  {status} - {detail.get('hashtag')}: {detail.get('reason')}")

            logger.info(f"过滤后的bodytext: {filtered_body}")
            
            result = {
                "filtered_body": filtered_body,
                "original_body": original_body,
                "removed_hashtags": removed_hashtags,
                "kept_hashtags": kept_hashtags,
                "filter_details": filter_details
            }

            logger.info("=" * 80)

            return result

        except Exception as e:
            logger.error(f"内容过滤失败: {e}", exc_info=True)
            # 失败时返回原始内容
            return {
                "filtered_body": text_data.get("body", ""),
                "original_body": text_data.get("body", ""),
                "removed_hashtags": [],
                "kept_hashtags": [],
                "filter_details": [],
                "error": str(e)
            }

    def _extract_hashtags(self, text: str) -> List[str]:
        """从文本中提取所有标签

        Args:
            text: 文本内容

        Returns:
            标签列表（去重）
        """
        # 匹配 #标签 格式（支持中英文、数字、下划线）
        pattern = r'#([A-Za-z0-9_\u4e00-\u9fa5]+)'
        hashtags = re.findall(pattern, text)

        # 去重并保持顺序
        seen = set()
        unique_hashtags = []
        for tag in hashtags:
            if tag not in seen:
                seen.add(tag)
                unique_hashtags.append(f"#{tag}")

        return unique_hashtags

    def _filter_content(
        self,
        text_data: Dict[str, Any],
        images: List[str],
        original_body: str,
        hashtags: List[str]
    ) -> Dict[str, Any]:
        """执行内容过滤

        Args:
            text_data: 文本数据（包含title、body）
            images: 图片URL列表
            original_body: 原始bodytext
            hashtags: 提取的标签列表

        Returns:
            过滤结果，包含filtered_body和filter_details
        """
        # 构建帖子内容摘要
        content_parts = []

        if text_data.get("title"):
            content_parts.append(f"**标题**: {text_data['title']}")

        # 只展示去除标签后的正文核心内容
        body_without_tags = original_body
        for tag in hashtags:
            body_without_tags = body_without_tags.replace(tag, "").strip()

        if body_without_tags:
            content_parts.append(f"**正文**: {body_without_tags}")

        content_summary = "\n".join(content_parts) if content_parts else "无文本内容"

        # 构建标签列表
        hashtags_text = "\n".join([f"{i+1}. {tag}" for i, tag in enumerate(hashtags)])

        # 构建prompt（明确区分原始和纯净内容）
        prompt = f"""# 帖子内容（不含标签）

{content_summary}

{'(包含 ' + str(len(images)) + ' 张图片)' if images else '(无图片)'}

# 待判断的标签

{hashtags_text}

# 原始bodytext（含标签）

{original_body}

# 任务

1. 基于"帖子内容（不含标签）"判断每个标签是否与内容相关
2. 从"原始bodytext"中移除不相关的标签，生成过滤后的bodytext

# 输出（JSON）

{{
  "filter_details": [
    {{"hashtag": "#标签", "is_relevant": true/false, "reason": "简洁理由"}}
  ],
  "filtered_body": "移除不相关标签后的bodytext"
}}"""

        # 构建多模态消息
        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={
                "filter_details": [
                    {"hashtag": tag, "is_relevant": True, "reason": "过滤失败，保留原标签"}
                    for tag in hashtags
                ],
                "filtered_body": original_body
            }
        )

        return result

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

        本 Agent 在 process 方法中直接构建消息
        """
        return []

    def _update_state(self, state: Dict[str, Any], response: Any) -> Dict[str, Any]:
        """更新状态 - ContentFilterAgent 不使用此方法

        本 Agent 在 process 方法中直接返回结果
        """
        return state
