import argparse
import asyncio
import os
import sys
from typing import List, Dict, Any, Optional

# 强制使用 utf-8，避免控制台编码报错影响 Embedding 加载
try:
    if hasattr(sys.stdout, "reconfigure"):
        sys.stdout.reconfigure(encoding="utf-8")
    if hasattr(sys.stderr, "reconfigure"):
        sys.stderr.reconfigure(encoding="utf-8")
except Exception:
    pass

# 确保能导入 src.*
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

from src.common.logger import get_logger
from src.config.config import global_config
from src.chat.knowledge import lpmm_start_up
from src.memory_system.retrieval_tools.query_lpmm_knowledge import query_lpmm_knowledge

logger = get_logger("test_lpmm_retrieval")


DEFAULT_TEST_CASES: List[Dict[str, Any]] = [
    {
        "name": "回滚一批知识",
        "query": "LPMM是什么?",
        "expect_keywords": ["哈希列表", "删除脚本", "OpenIE"],
    },
    {
        "name": "调整 LPMM 检索参数",
        "query": "不同用词习惯带来的检索偏差该如何解决",
        "expect_keywords": ["bot_config.toml", "lpmm_knowledge", "qa_paragraph_search_top_k"],
    },
]


async def run_tests(test_cases: Optional[List[Dict[str, Any]]] = None) -> None:
    """简单测试 LPMM 知识库检索能力"""
    if not global_config.lpmm_knowledge.enable:
        logger.warning("当前配置中 lpmm_knowledge.enable 为 False，检索测试可能直接返回“未启用”。")

    logger.info("开始初始化 LPMM 知识库...")
    lpmm_start_up()
    logger.info("LPMM 知识库初始化完成，开始执行测试用例。")

    cases = test_cases if test_cases is not None else DEFAULT_TEST_CASES

    for case in cases:
        name = case["name"]
        query = case["query"]
        expect_keywords: List[str] = case.get("expect_keywords", [])

        print("\n" + "=" * 60)
        print(f"[TEST] {name}")
        print(f"[Q] {query}")

        result = await query_lpmm_knowledge(query, limit=3)

        print("\n[RAW RESULT]")
        print(result)

        status = "UNKNOWN"
        hit_keywords: List[str] = []

        if isinstance(result, str):
            if "未启用" in result or "未初始化" in result or "查询失败" in result:
                status = "ERROR"
            elif "未找到与" in result:
                status = "NO_HIT"
            else:
                if expect_keywords:
                    hit_keywords = [kw for kw in expect_keywords if kw in result]
                    status = "PASS" if hit_keywords else "WARN"
                else:
                    status = "PASS"

        print("\n[CHECK]")
        print(f"Status: {status}")
        if expect_keywords:
            print(f"Expected keywords: {expect_keywords}")
            print(f"Hit keywords: {hit_keywords}")

    print("\n" + "=" * 60)
    print("LPMM 检索测试完成。请根据每条用例的 Status 和命中关键词判断检索效果是否符合预期。")


def main() -> None:
    parser = argparse.ArgumentParser(
        description=(
            "测试 LPMM 知识库检索能力。\n"
            "如不提供参数，则执行内置的默认用例；\n"
            "也可以通过 --query 与 --expect-keyword 自定义一条测试用例。"
        )
    )
    parser.add_argument(
        "--query",
        help="自定义测试问题（单条）。提供该参数时，将仅运行这一条用例。",
    )
    parser.add_argument(
        "--expect-keyword",
        action="append",
        help="期望在检索结果中出现的关键字，可重复多次指定；仅在提供 --query 时生效。",
    )
    args = parser.parse_args()

    if args.query:
        custom_case = {
            "name": "custom",
            "query": args.query,
            "expect_keywords": args.expect_keyword or [],
        }
        asyncio.run(run_tests([custom_case]))
    else:
        asyncio.run(run_tests())


if __name__ == "__main__":
    main()
