import asyncio
import json
from unittest.mock import AsyncMock, MagicMock, patch

from app.agent.tools.impl._torrent_search_utils import simplify_search_result
from app.agent.tools.impl.get_search_results import GetSearchResultsTool
from app.domain.context import Context, TorrentInfo


def _build_context(
    title: str,
    *,
    description: str = None,
    labels: list = None,
    index: int = 1,
) -> Context:
    """构造种子搜索结果上下文。"""
    return Context(
        torrent_info=TorrentInfo(
            title=title,
            description=description,
            labels=labels or [],
            enclosure=f"https://example.com/download/{index}",
            size=1024,
            seeders=index,
            site_name="测试站点",
        )
    )


def _run_tool(items: list[Context], **kwargs) -> str:
    """使用指定缓存结果运行搜索结果工具。"""
    search_chain = MagicMock()
    search_chain.async_last_search_results = AsyncMock(return_value=items)
    with patch(
        "app.agent.tools.impl.get_search_results.SearchChain",
        return_value=search_chain,
    ):
        return asyncio.run(
            GetSearchResultsTool(session_id="session-1", user_id="10001").run(
                **kwargs
            )
        )


def test_simplify_search_result_only_includes_description_when_requested():
    """精简结果应按参数控制简介输出，避免默认增加上下文长度。"""
    context = _build_context("Movie.2026.1080p", description="简繁特效字幕")

    default_result = simplify_search_result(context, 1)
    detailed_result = simplify_search_result(context, 1, include_description=True)

    assert "description" not in default_result["torrent_info"]
    assert detailed_result["torrent_info"]["description"] == "简繁特效字幕"


def test_simplify_search_result_only_includes_labels_when_requested():
    """精简结果应按参数控制标签输出，避免默认增加上下文长度。"""
    context = _build_context("Movie.2026.1080p", labels=["官译", "特效"])

    default_result = simplify_search_result(context, 1)
    detailed_result = simplify_search_result(context, 1, include_labels=True)

    assert "labels" not in default_result["torrent_info"]
    assert detailed_result["torrent_info"]["labels"] == ["官译", "特效"]


def test_content_pattern_matches_title_description_and_labels():
    """内容正则应联合匹配标题、简介和标签，并可返回命中的简介。"""
    items = [
        _build_context("Movie.Special.Effect.2026", description="普通字幕", index=1),
        _build_context("Movie.2026.1080p", description="简繁特效字幕", index=2),
        _build_context("Movie.2026.2160p", description="国语音轨", labels=["官译"], index=3),
        _build_context("Movie.2026.WEB-DL", description="英文字幕", index=4),
    ]

    result = _run_tool(
        items,
        content_pattern="Special.Effect|特效字幕|官译",
        include_description=True,
    )
    payload = json.loads(result)

    assert payload["total_count"] == 3
    assert [item["torrent_info"]["description"] for item in payload["results"]] == [
        "普通字幕",
        "简繁特效字幕",
        "国语音轨",
    ]


def test_title_pattern_keeps_title_only_matching_semantics():
    """标题正则不应因新增内容筛选而匹配简介或标签。"""
    items = [
        _build_context("Movie.特效.2026", description="普通字幕", index=1),
        _build_context("Movie.2026.1080p", description="简繁特效字幕", index=2),
        _build_context("Movie.2026.2160p", labels=["特效"], index=3),
    ]

    result = _run_tool(items, title_pattern="特效", include_description=True)
    payload = json.loads(result)

    assert payload["total_count"] == 1
    assert payload["results"][0]["torrent_info"]["title"] == "Movie.特效.2026"


def test_invalid_content_pattern_returns_validation_message():
    """非法内容正则应返回明确错误，不进入搜索结果筛选。"""
    result = _run_tool([_build_context("Movie.2026")], content_pattern="[")

    assert result.startswith("正则表达式格式错误:")
