"""Unit tests for ``advanced_search_system.tools.fetch.build_fetch_tool``.

Pins the mode dispatch and the prompt-content contract for the two
summary variants (focus-only vs focus + overall query). Avoids any real
HTTP — patches ``ContentFetcher`` and the model.
"""

from __future__ import annotations

from unittest.mock import MagicMock, patch

import pytest

from local_deep_research.advanced_search_system.strategies.langgraph_agent_strategy import (
    SearchResultsCollector,
)
from local_deep_research.advanced_search_system.tools.fetch import (
    FETCH_MODES,
    build_fetch_tool,
)


def _fetcher_cm(*, status="success", title="Page", content="Body text"):
    fetcher = MagicMock()
    fetcher.fetch.return_value = {
        "status": status,
        "title": title,
        "content": content,
    }
    cm = MagicMock()
    cm.__enter__.return_value = fetcher
    cm.__exit__.return_value = False
    return cm


def _model_returning(text: str):
    """A model whose ``invoke`` returns an object with ``.content == text``."""
    msg = MagicMock()
    msg.content = text
    model = MagicMock()
    model.invoke.return_value = msg
    return model


def test_fetch_modes_constant_lists_all_supported_values():
    assert FETCH_MODES == (
        "disabled",
        "full",
        "summary_focus",
        "summary_focus_query",
    )


def test_disabled_mode_returns_none():
    assert build_fetch_tool("disabled", SearchResultsCollector([])) is None


def test_full_mode_returns_tool_with_url_only_signature():
    tool = build_fetch_tool("full", SearchResultsCollector([]))
    assert tool is not None
    assert "url" in tool.args
    assert "focus" not in tool.args


def test_summary_focus_requires_model():
    with pytest.raises(ValueError, match="summary_focus"):
        build_fetch_tool("summary_focus", SearchResultsCollector([]))


def test_summary_focus_query_requires_model():
    with pytest.raises(ValueError, match="summary_focus_query"):
        build_fetch_tool("summary_focus_query", SearchResultsCollector([]))


def test_summary_focus_tool_calls_model_with_focus_only_prompt():
    collector = SearchResultsCollector([])
    model = _model_returning("relevant fact 1")
    tool = build_fetch_tool(
        "summary_focus",
        collector,
        model=model,
        overall_query="should not appear",
    )
    assert tool is not None
    assert "focus" in tool.args

    cm = _fetcher_cm(title="T", content="page body")
    with patch(
        "local_deep_research.content_fetcher.ContentFetcher", return_value=cm
    ):
        out = tool.invoke({"url": "http://example.com/", "focus": "year of X"})

    model.invoke.assert_called_once()
    prompt = model.invoke.call_args[0][0]
    # focus-only mode must NOT mention the overall query, even if one was passed
    assert "Why this page was fetched: year of X" in prompt
    assert "Overall research question" not in prompt
    # Output is prefixed with citation index so the agent can cite consistently
    assert out.startswith("[1] ")
    assert "relevant fact 1" in out


def test_summary_focus_query_includes_overall_query_in_prompt():
    collector = SearchResultsCollector([])
    model = _model_returning("relevant fact 2")
    tool = build_fetch_tool(
        "summary_focus_query",
        collector,
        model=model,
        overall_query="When did Liepmann receive the Prandtl-Ring Award?",
    )
    cm = _fetcher_cm(title="T", content="page body")
    with patch(
        "local_deep_research.content_fetcher.ContentFetcher", return_value=cm
    ):
        tool.invoke({"url": "http://example.com/", "focus": "year"})

    prompt = model.invoke.call_args[0][0]
    assert (
        "Overall research question: When did Liepmann receive the Prandtl-Ring Award?"
        in prompt
    )
    assert "Why this page was fetched: year" in prompt


def test_summary_focus_query_with_empty_overall_query_falls_back_to_focus_only():
    """An empty overall_query should not produce a stale 'Overall research question:' line."""
    collector = SearchResultsCollector([])
    model = _model_returning("ok")
    tool = build_fetch_tool(
        "summary_focus_query",
        collector,
        model=model,
        overall_query="",  # empty
    )
    cm = _fetcher_cm()
    with patch(
        "local_deep_research.content_fetcher.ContentFetcher", return_value=cm
    ):
        tool.invoke({"url": "http://example.com/", "focus": "x"})

    prompt = model.invoke.call_args[0][0]
    assert "Overall research question" not in prompt


def test_unknown_mode_raises_with_valid_modes_listed():
    with pytest.raises(ValueError, match="Unknown fetch mode"):
        build_fetch_tool("magic", SearchResultsCollector([]))
