"""
统一历史对话管理器
整合所有分散的 parse_history / _parse_history / build_history_str / filter_image_urls 逻辑
"""

import json
from typing import Any, Dict, List, Optional


class HistoryManager:
    """统一的历史对话管理器，提供解析、截断、格式化、过滤等功能"""

    def __init__(
        self,
        max_messages: int = 8,
        max_assistant_chars: int = 300,
    ):
        """
        Args:
            max_messages: 保留的最近消息条数
            max_assistant_chars: assistant 角色内容截断字符数
        """
        self.max_messages = max_messages
        self.max_assistant_chars = max_assistant_chars

    # ==================== 解析 ====================

    def parse(self, history_message: Any) -> List[Dict[str, Any]]:
        """
        解析历史消息为列表，保留最近 max_messages 条。
        兼容字符串和列表输入，替代所有 parse_history / _parse_history。
        """
        if not history_message:
            return []
        try:
            data = json.loads(history_message) if isinstance(history_message, str) else history_message
            return data[-self.max_messages:] if isinstance(data, list) else []
        except Exception:
            return []

    # ==================== 截断 ====================

    def truncate(self, messages: List[Dict[str, Any]], keep_recent: Optional[int] = None) -> List[Dict[str, Any]]:
        """按数量截断，保留最近 keep_recent 条"""
        if not messages:
            return []
        n = keep_recent if keep_recent is not None else self.max_messages
        return messages[-n:]

    # ==================== 格式化 ====================

    def to_prompt_str(
        self,
        messages: List[Dict[str, Any]],
        recent_count: Optional[int] = None,
        assistant_truncate: Optional[int] = None,
    ) -> str:
        """
        格式化为 "用户: xxx\\n助手: xxx" 纯文本字符串，用于 prompt 注入。
        替代 build_history_str。
        """
        if not messages:
            return ""
        n = recent_count if recent_count is not None else self.max_messages
        trunc = assistant_truncate if assistant_truncate is not None else self.max_assistant_chars
        recent = messages[-n:]
        parts = []
        for m in recent:
            if isinstance(m, dict):
                role = m.get("role", "")
                content = (m.get("content") or "").strip()
                if role == "user":
                    parts.append(f"用户: {content}")
                elif role == "assistant":
                    parts.append(f"助手: {content[:trunc]}")
        return "\n".join(parts) if parts else ""

    def to_openai_messages(self, messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        格式化为 OpenAI messages 列表，直接传入 LLM。
        用于百科问答等需要完整消息格式的场景。
        """
        if not messages:
            return []
        result = []
        for m in messages:
            if isinstance(m, dict) and m.get("role") and m.get("content"):
                result.append({"role": m["role"], "content": m["content"]})
        return result

    # ==================== 请求预处理 ====================

    def preprocess_from_request(self, history_message: Any, exclude_last: bool = True) -> str:
        """
        处理前端传入的历史消息：解析、移除当前用户消息、序列化。
        对应 app.py 中 history_message 预处理逻辑。

        Args:
            history_message: 前端传入的历史消息，支持 str 或 list
            exclude_last: 是否移除最后一条（当前用户消息），默认 True

        Returns:
            处理后的 JSON 字符串
        """
        if not history_message:
            return ""
        try:
            data = json.loads(history_message) if isinstance(history_message, str) else history_message
        except (json.JSONDecodeError, TypeError):
            return ""
        if not isinstance(data, list):
            return ""
        if exclude_last and data:
            data = data[:-1]
        return json.dumps(data, ensure_ascii=False)

    # ==================== 状态初始化 ====================

    def init_history(self, history_message: Any) -> Dict[str, Any]:
        """
        一步完成历史消息解析，返回 history_message(str) + history_messages(list) 双字段。
        用于各工作流入口初始化 state，消除重复的 parse_history 调用。

        Args:
            history_message: 历史消息，支持 str 或 list

        Returns:
            {"history_message": str, "history_messages": list}
        """
        parsed = self.parse(history_message)
        raw = json.dumps(parsed, ensure_ascii=False) if parsed else ""
        return {"history_message": raw, "history_messages": parsed}

    # ==================== 过滤 ====================

    @staticmethod
    def filter_image_urls(history_message: Any) -> Any:
        """
        过滤历史消息中的图片URL，将多模态内容转为纯文本。
        替代 main_agent.filter_image_urls。
        """
        if not history_message:
            return history_message

        try:
            history_messages = json.loads(history_message) if isinstance(history_message, str) else history_message
        except (json.JSONDecodeError, TypeError):
            return history_message

        if not isinstance(history_messages, list):
            return history_messages

        filtered_messages = []
        for msg in history_messages:
            if not isinstance(msg, dict):
                filtered_messages.append(msg)
                continue

            new_msg = msg.copy()
            content = msg.get("content")

            if isinstance(content, list):
                text_parts = []
                for content_item in content:
                    if isinstance(content_item, dict):
                        if content_item.get("type") == "text":
                            text_value = content_item.get("text", "")
                            if text_value:
                                text_parts.append(text_value)
                    elif isinstance(content_item, str):
                        text_parts.append(content_item)

                if text_parts:
                    new_msg["content"] = "".join(text_parts)
                    filtered_messages.append(new_msg)
            else:
                filtered_messages.append(new_msg)

        return filtered_messages


# ==================== 模块级便捷实例 ====================
# 提供与旧函数签名兼容的模块级函数，方便渐进式迁移

_default_manager = HistoryManager()


def parse_history(history_message: Any) -> List[Dict[str, Any]]:
    """兼容旧调用的模块级函数"""
    return _default_manager.parse(history_message)


def build_history_str(
    history_messages: List[Dict[str, Any]],
    recent_count: int = 4,
    assistant_truncate: int = 300,
) -> str:
    """兼容旧调用的模块级函数"""
    mgr = HistoryManager(max_messages=recent_count, max_assistant_chars=assistant_truncate)
    return mgr.to_prompt_str(history_messages, recent_count=recent_count, assistant_truncate=assistant_truncate)


def filter_image_urls(history_message: Any) -> Any:
    """兼容旧调用的模块级函数"""
    return HistoryManager.filter_image_urls(history_message)


def preprocess_from_request(history_message: Any, exclude_last: bool = True) -> str:
    """兼容旧调用的模块级函数"""
    return _default_manager.preprocess_from_request(history_message, exclude_last=exclude_last)


def init_history(history_message: Any) -> Dict[str, Any]:
    """兼容旧调用的模块级函数"""
    return _default_manager.init_history(history_message)


