import random
from typing import List, Optional

from src.common.logger import get_logger
from src.config.config import global_config, model_config
from src.chat.utils.prompt_builder import Prompt
from src.llm_models.payload_content.message import RoleType, Message
from src.llm_models.utils_model import LLMRequest
from src.chat.message_receive.chat_stream import get_chat_manager
from src.plugin_system.apis import send_api

logger = get_logger("dream_generator")

# 初始化 utils 模型用于生成梦境总结
_dream_summary_model: Optional[LLMRequest] = None

# 梦境风格列表（21种）
DREAM_STYLES = [
    "保持诗意和想象力，自由编写",
    "诗意朦胧，如薄雾笼罩的清晨",
    "奇幻冒险，充满未知与探索",
    "温暖怀旧，带着时光的痕迹",
    "神秘悬疑，暗藏深意",
    "浪漫唯美，如诗如画",
    "科幻未来，科技与想象交织",
    "自然清新，如山林间的微风",
    "深沉哲思，引人深思",
    "轻松幽默，充满趣味",
    "悲伤忧郁，带着淡淡哀愁",
    "激昂热烈，充满活力",
    "宁静平和，如湖面般平静",
    "荒诞离奇，打破常规",
    "细腻温柔，如春风拂面",
    "壮阔宏大，气势磅礴",
    "简约纯粹，返璞归真",
    "复杂多变，层次丰富",
    "梦幻迷离，虚实难辨",
    "现实写意，贴近生活",
    "抽象概念，超越具象",
]


def get_random_dream_styles(count: int = 2) -> List[str]:
    """从梦境风格列表中随机选择指定数量的风格"""
    return random.sample(DREAM_STYLES, min(count, len(DREAM_STYLES)))

def init_dream_summary_prompt() -> None:
    """初始化梦境总结的提示词"""
    Prompt(
        """
你刚刚完成了一次对聊天记录的记忆整理工作。以下是整理过程的摘要：
整理过程：
{conversation_text}

请将这次整理涉及的相关信息改写为一个富有诗意和想象力的"梦境"，请你仅使用具体的记忆的内容，而不是整理过程编写。
要求：
1. 使用第一人称视角
2. 叙述直白，不要复杂修辞，口语化
3. 长度控制在200-800字
4. 用中文输出
梦境风格：
{dream_styles}
请直接输出梦境内容，不要添加其他说明：
""",
        name="dream_summary_prompt",
    )


async def generate_dream_summary(
    chat_id: str,
    conversation_messages: List[Message],
    total_iterations: int,
    time_cost: float,
) -> None:
    """生成梦境总结，输出到日志，并根据配置可选地推送给指定用户"""
    try:
        import json
        from src.chat.utils.prompt_builder import global_prompt_manager

        # 第一步：建立工具调用结果映射 (call_id -> result)
        tool_results_map: dict[str, str] = {}
        for msg in conversation_messages:
            if msg.role == RoleType.Tool and msg.tool_call_id:
                content = ""
                if msg.content:
                    if isinstance(msg.content, list) and msg.content:
                        content = msg.content[0].text if hasattr(msg.content[0], "text") else str(msg.content[0])
                    else:
                        content = str(msg.content)
                tool_results_map[msg.tool_call_id] = content

        # 第二步：详细记录所有工具调用操作和结果到日志
        tool_call_count = 0
        logger.info(f"[dream][工具调用详情] 开始记录 chat_id={chat_id} 的所有工具调用操作：")

        for msg in conversation_messages:
            if msg.role == RoleType.Assistant and msg.tool_calls:
                tool_call_count += 1
                # 提取思考内容
                thought_content = ""
                if msg.content:
                    if isinstance(msg.content, list) and msg.content:
                        thought_content = (
                            msg.content[0].text if hasattr(msg.content[0], "text") else str(msg.content[0])
                        )
                    else:
                        thought_content = str(msg.content)

                logger.info(f"[dream][工具调用详情] === 第 {tool_call_count} 组工具调用 ===")
                if thought_content:
                    logger.info(
                        f"[dream][工具调用详情] 思考内容：{thought_content[:500]}{'...' if len(thought_content) > 500 else ''}"
                    )

                # 记录每个工具调用的详细信息
                for idx, tool_call in enumerate(msg.tool_calls, 1):
                    tool_name = tool_call.func_name
                    tool_args = tool_call.args or {}
                    tool_call_id = tool_call.call_id
                    tool_result = tool_results_map.get(tool_call_id, "未找到执行结果")

                    # 格式化参数
                    try:
                        args_str = json.dumps(tool_args, ensure_ascii=False, indent=2) if tool_args else "无参数"
                    except Exception:
                        args_str = str(tool_args)

                    logger.info(f"[dream][工具调用详情] --- 工具 {idx}: {tool_name} ---")
                    logger.info(f"[dream][工具调用详情] 调用参数：\n{args_str}")
                    logger.info(f"[dream][工具调用详情] 执行结果：\n{tool_result}")
                    logger.info(f"[dream][工具调用详情] {'-' * 60}")

        logger.info(f"[dream][工具调用详情] 共记录了 {tool_call_count} 组工具调用操作")

        # 第三步：构建对话历史摘要（用于生成梦境）
        conversation_summary = []
        for msg in conversation_messages:
            role = msg.role.value if hasattr(msg.role, "value") else str(msg.role)
            content = ""
            if msg.content:
                content = msg.content[0].text if isinstance(msg.content, list) and msg.content else str(msg.content)

            if role == "user" and "轮次信息" in content:
                # 跳过轮次信息消息
                continue

            if role == "assistant":
                # 只保留思考内容，简化工具调用信息
                if content:
                    # 截取前500字符，避免过长
                    content_preview = content[:500] + ("..." if len(content) > 500 else "")
                    conversation_summary.append(f"[{role}] {content_preview}")
            elif role == "tool":
                # 工具结果，只保留关键信息
                if content:
                    # 截取前300字符
                    content_preview = content[:300] + ("..." if len(content) > 300 else "")
                    conversation_summary.append(f"[工具执行] {content_preview}")

        conversation_text = "\n".join(conversation_summary[-20:])  # 只保留最后20条消息

        # 随机选择2个梦境风格
        selected_styles = get_random_dream_styles(2)
        dream_styles_text = "\n".join([f"{i + 1}. {style}" for i, style in enumerate(selected_styles)])

        # 使用 Prompt 管理器格式化梦境生成 prompt
        dream_prompt = await global_prompt_manager.format_prompt(
            "dream_summary_prompt",
            chat_id=chat_id,
            total_iterations=total_iterations,
            time_cost=time_cost,
            conversation_text=conversation_text,
            dream_styles=dream_styles_text,
        )

        # 调用 utils 模型生成梦境
        summary_model = LLMRequest(
            model_set=model_config.model_task_config.replyer,
            request_type="dream.summary",
        )
        dream_content, (reasoning, model_name, _) = await summary_model.generate_response_async(
            dream_prompt,
            temperature=0.8,
        )

        if dream_content:
            logger.info(f"[dream][梦境总结] 对 chat_id={chat_id} 的整理过程梦境：\n{dream_content}")

            # 第五步：根据配置决定是否将梦境发送给指定用户
            try:
                dream_send_raw = getattr(global_config.dream, "dream_send", "") or ""
                dream_send = dream_send_raw.strip()
                if dream_send:
                    parts = dream_send.split(":")
                    if len(parts) != 2:
                        logger.warning(
                            f"[dream][梦境总结] dream_send 配置格式不正确，应为 'platform:user_id'，当前值: {dream_send_raw!r}"
                        )
                    else:
                        platform, user_id = parts[0].strip(), parts[1].strip()
                        if not platform or not user_id:
                            logger.warning(
                                f"[dream][梦境总结] dream_send 平台或用户ID为空，当前值: {dream_send_raw!r}"
                            )
                        else:
                            # 默认为私聊会话
                            stream_id = get_chat_manager().get_stream_id(
                                platform=platform,
                                id=str(user_id),
                                is_group=False,
                            )
                            if not stream_id:
                                logger.error(
                                    f"[dream][梦境总结] 无法根据 dream_send 找到有效的聊天流，"
                                    f"platform={platform!r}, user_id={user_id!r}"
                                )
                            else:
                                dream_visible = global_config.dream.dream_visible
                                ok = await send_api.text_to_stream(
                                    dream_content,
                                    stream_id=stream_id,
                                    typing=False,
                                    storage_message=dream_visible,
                                )
                                if ok:
                                    logger.info(
                                        f"[dream][梦境总结] 已将梦境结果发送给配置的目标用户: {platform}:{user_id}"
                                    )
                                else:
                                    logger.error(
                                        f"[dream][梦境总结] 向 {platform}:{user_id} 发送梦境结果失败"
                                    )
            except Exception as send_exc:
                logger.error(f"[dream][梦境总结] 发送梦境结果到配置用户时出错: {send_exc}", exc_info=True)
        else:
            logger.warning("[dream][梦境总结] 未能生成梦境总结")

    except Exception as e:
        logger.error(f"[dream][梦境总结] 生成梦境总结失败: {e}", exc_info=True)


init_dream_summary_prompt()
