import json
from typing import List, Optional

from src.common.logger import get_logger
from src.common.database.database_model import ChatHistory
from src.chat.utils.utils import parse_keywords_string

logger = get_logger("dream_agent")


def make_search_chat_history(chat_id: str):
    async def search_chat_history(
        keyword: Optional[str] = None,
        participant: Optional[str] = None,
    ) -> str:
        """根据关键词或参与人查询记忆，返回匹配的记忆id、记忆标题theme和关键词keywords（dream 维护专用版本）"""
        try:
            # 检查参数
            if not keyword and not participant:
                return "未指定查询参数（需要提供keyword或participant之一）"

            logger.info(
                f"[dream][tool] 调用 search_chat_history(keyword={keyword}, participant={participant}) "
                f"(作用域 chat_id={chat_id})"
            )

            # 构建查询条件
            query = ChatHistory.select().where(ChatHistory.chat_id == chat_id)

            # 执行查询（按时间倒序，最近的在前）
            records = list(query.order_by(ChatHistory.start_time.desc()).limit(50))

            filtered_records: List[ChatHistory] = []

            for record in records:
                participant_matched = True  # 如果没有participant条件，默认为True
                keyword_matched = True  # 如果没有keyword条件，默认为True

                # 检查参与人匹配
                if participant:
                    participant_matched = False
                    participants_list: List[str] = []
                    if record.participants:
                        try:
                            participants_data = (
                                json.loads(record.participants)
                                if isinstance(record.participants, str)
                                else record.participants
                            )
                            if isinstance(participants_data, list):
                                participants_list = [str(p).lower() for p in participants_data]
                        except (json.JSONDecodeError, TypeError, ValueError):
                            pass

                    participant_lower = participant.lower().strip()
                    if participant_lower and any(participant_lower in p for p in participants_list):
                        participant_matched = True

                # 检查关键词匹配
                if keyword:
                    keyword_matched = False
                    # 解析多个关键词（支持空格、逗号等分隔符）
                    keywords_list = parse_keywords_string(keyword)
                    if not keywords_list:
                        keywords_list = [keyword.strip()] if keyword.strip() else []

                    # 转换为小写以便匹配
                    keywords_lower = [kw.lower() for kw in keywords_list if kw.strip()]

                    if keywords_lower:
                        # 在theme、keywords、summary、original_text中搜索
                        theme = (record.theme or "").lower()
                        summary = (record.summary or "").lower()
                        original_text = (record.original_text or "").lower()

                        # 解析record中的keywords JSON
                        record_keywords_list: List[str] = []
                        if record.keywords:
                            try:
                                keywords_data = (
                                    json.loads(record.keywords) if isinstance(record.keywords, str) else record.keywords
                                )
                                if isinstance(keywords_data, list):
                                    record_keywords_list = [str(k).lower() for k in keywords_data]
                            except (json.JSONDecodeError, TypeError, ValueError):
                                pass

                        # 有容错的全匹配：如果关键词数量>2，允许n-1个关键词匹配；否则必须全部匹配
                        matched_count = 0
                        for kw in keywords_lower:
                            kw_matched = (
                                kw in theme
                                or kw in summary
                                or kw in original_text
                                or any(kw in k for k in record_keywords_list)
                            )
                            if kw_matched:
                                matched_count += 1

                        # 计算需要匹配的关键词数量
                        total_keywords = len(keywords_lower)
                        if total_keywords > 2:
                            # 关键词数量>2，允许n-1个关键词匹配
                            required_matches = total_keywords - 1
                        else:
                            # 关键词数量<=2，必须全部匹配
                            required_matches = total_keywords

                        keyword_matched = matched_count >= required_matches

                # 两者都匹配（如果同时有participant和keyword，需要两者都匹配；如果只有一个条件，只需要该条件匹配）
                matched = participant_matched and keyword_matched

                if matched:
                    filtered_records.append(record)

            if not filtered_records:
                if keyword and participant:
                    keywords_str = "、".join(parse_keywords_string(keyword) if keyword else [])
                    return f"未找到包含关键词'{keywords_str}'且参与人包含'{participant}'的聊天记录"
                elif keyword:
                    keywords_list = parse_keywords_string(keyword)
                    keywords_str = "、".join(keywords_list)
                    if len(keywords_list) > 2:
                        required_count = len(keywords_list) - 1
                        return f"未找到包含至少{required_count}个关键词（共{len(keywords_list)}个）'{keywords_str}'的聊天记录"
                    else:
                        return f"未找到包含所有关键词'{keywords_str}'的聊天记录"
                elif participant:
                    return f"未找到参与人包含'{participant}'的聊天记录"
                else:
                    return "未找到相关聊天记录"

            # 如果匹配结果超过20条，不返回具体记录，只返回提示和所有相关关键词
            if len(filtered_records) > 20:
                all_keywords_set = set()
                for record in filtered_records:
                    if record.keywords:
                        try:
                            keywords_data = (
                                json.loads(record.keywords) if isinstance(record.keywords, str) else record.keywords
                            )
                            if isinstance(keywords_data, list):
                                for k in keywords_data:
                                    k_str = str(k).strip()
                                    if k_str:
                                        all_keywords_set.add(k_str)
                        except (json.JSONDecodeError, TypeError, ValueError):
                            continue

                search_label = keyword or participant or "当前条件"

                if all_keywords_set:
                    keywords_str = "、".join(sorted(all_keywords_set))
                    response_text = (
                        f"包含“{search_label}”的结果过多，请尝试更多关键词精确查找\n\n"
                        f'有关"{search_label}"的关键词：\n'
                        f"{keywords_str}"
                    )
                else:
                    response_text = (
                        f"包含“{search_label}”的结果过多，请尝试更多关键词精确查找\n\n"
                        f'有关"{search_label}"的关键词信息为空'
                    )

                logger.info(
                    f"[dream][tool] search_chat_history 匹配结果超过20条，返回关键词汇总提示，总数={len(filtered_records)}"
                )
                return response_text

            # 构建结果文本，返回id、theme和keywords（最多20条）
            results: List[str] = []
            for record in filtered_records[:20]:
                result_parts: List[str] = []

                # 记忆ID
                result_parts.append(f"记忆ID：{record.id}")

                # 主题
                if record.theme:
                    result_parts.append(f"主题：{record.theme}")
                else:
                    result_parts.append("主题：（无）")

                # 关键词
                if record.keywords:
                    try:
                        keywords_data = (
                            json.loads(record.keywords) if isinstance(record.keywords, str) else record.keywords
                        )
                        if isinstance(keywords_data, list) and keywords_data:
                            keywords_str = "、".join([str(k) for k in keywords_data])
                            result_parts.append(f"关键词：{keywords_str}")
                        else:
                            result_parts.append("关键词：（无）")
                    except (json.JSONDecodeError, TypeError, ValueError):
                        result_parts.append("关键词：（无）")
                else:
                    result_parts.append("关键词：（无）")

                results.append("\n".join(result_parts))

            if not results:
                return "未找到相关聊天记录"

            response_text = "\n\n---\n\n".join(results)

            logger.info(f"[dream][tool] search_chat_history 返回 {len(filtered_records)} 条匹配记录")
            return response_text
        except Exception as e:
            logger.error(f"search_chat_history 失败: {e}")
            return f"search_chat_history 执行失败: {e}"

    return search_chat_history

