import pytest
from unittest.mock import AsyncMock, MagicMock, patch

from fabledassistant.services.tools.web import lookup_tool


@pytest.mark.asyncio
async def test_lookup_wikipedia_hit():
    wiki_data = {
        "title": "QUIC",
        "extract": "QUIC is a transport layer protocol.",
        "url": "https://en.wikipedia.org/wiki/QUIC",
        "thumbnail_url": "",
    }

    with patch("fabledassistant.services.wikipedia.wiki_summary", new_callable=AsyncMock, return_value=wiki_data), \
         patch("fabledassistant.config.Config") as mock_config:
        mock_config.searxng_enabled.return_value = False
        result = await lookup_tool(user_id=1, arguments={"query": "QUIC"})

    assert result["success"] is True
    assert result["type"] == "lookup"
    assert result["data"]["wikipedia"]["title"] == "QUIC"
    assert result["data"]["web"] == []
    assert "image" not in result["data"]["wikipedia"]


@pytest.mark.asyncio
async def test_lookup_wikipedia_miss_searxng_fallback():
    searxng_results = [
        {"url": "https://example.com/quic", "title": "QUIC Explained", "snippet": "An overview..."},
    ]

    with patch("fabledassistant.services.wikipedia.wiki_summary", new_callable=AsyncMock, return_value=None), \
         patch("fabledassistant.config.Config") as mock_config, \
         patch("fabledassistant.services.research._search_searxng", new_callable=AsyncMock, return_value=searxng_results), \
         patch("fabledassistant.services.article_fetcher.fetch_article_text", new_callable=AsyncMock, return_value="Full article about QUIC..."):
        mock_config.searxng_enabled.return_value = True
        result = await lookup_tool(user_id=1, arguments={"query": "QUIC"})

    assert result["success"] is True
    assert result["data"]["wikipedia"] is None
    assert len(result["data"]["web"]) == 1
    assert result["data"]["web"][0]["url"] == "https://example.com/quic"


@pytest.mark.asyncio
async def test_lookup_parallel_both_sources():
    wiki_data = {
        "title": "President of the United States",
        "extract": "The president is the head of state.",
        "url": "https://en.wikipedia.org/wiki/President_of_the_United_States",
        "thumbnail_url": "",
    }
    searxng_results = [
        {"url": "https://whitehouse.gov", "title": "The White House", "snippet": "Current admin..."},
    ]

    with patch("fabledassistant.services.wikipedia.wiki_summary", new_callable=AsyncMock, return_value=wiki_data), \
         patch("fabledassistant.config.Config") as mock_config, \
         patch("fabledassistant.services.research._search_searxng", new_callable=AsyncMock, return_value=searxng_results), \
         patch("fabledassistant.services.article_fetcher.fetch_article_text", new_callable=AsyncMock, return_value="Current president is..."):
        mock_config.searxng_enabled.return_value = True
        result = await lookup_tool(user_id=1, arguments={"query": "president of the united states"})

    assert result["success"] is True
    assert result["data"]["wikipedia"]["title"] == "President of the United States"
    assert len(result["data"]["web"]) == 1


@pytest.mark.asyncio
async def test_lookup_wikipedia_thumbnail_cached():
    wiki_data = {
        "title": "Hedgehog",
        "extract": "Hedgehogs are spiny mammals.",
        "url": "https://en.wikipedia.org/wiki/Hedgehog",
        "thumbnail_url": "https://upload.wikimedia.org/.../Hedgehog.jpg",
    }
    mock_record = MagicMock()
    mock_record.id = 42

    with patch("fabledassistant.services.wikipedia.wiki_summary", new_callable=AsyncMock, return_value=wiki_data), \
         patch("fabledassistant.config.Config") as mock_config, \
         patch("fabledassistant.services.images.fetch_and_store_image", new_callable=AsyncMock, return_value=mock_record):
        mock_config.searxng_enabled.return_value = False
        result = await lookup_tool(user_id=1, arguments={"query": "hedgehog"})

    assert result["data"]["wikipedia"]["image"]["embed"] == "![Hedgehog](/api/images/42)"
    assert "Wikipedia" in result["data"]["wikipedia"]["image"]["citation"]
    assert "image_instructions" in result["data"]


@pytest.mark.asyncio
async def test_lookup_wikipedia_miss_no_searxng():
    with patch("fabledassistant.services.wikipedia.wiki_summary", new_callable=AsyncMock, return_value=None), \
         patch("fabledassistant.config.Config") as mock_config:
        mock_config.searxng_enabled.return_value = False
        result = await lookup_tool(user_id=1, arguments={"query": "xyznonexistent"})

    assert result["success"] is True
    assert "message" in result["data"]


@pytest.mark.asyncio
async def test_lookup_always_available():
    with patch("fabledassistant.services.tools._registry.is_caldav_configured", new_callable=AsyncMock, return_value=False), \
         patch("fabledassistant.services.settings.get_setting", new_callable=AsyncMock, return_value="false"):
        from fabledassistant.services.tools import get_tools_for_user
        tools = await get_tools_for_user(user_id=1)
        tool_names = {t["function"]["name"] for t in tools}
        assert "lookup" in tool_names
