from unittest.mock import AsyncMock, MagicMock

import pytest

from gsearch_mcp_cli.core.warmup import needs_warmup, warmup_profile
from gsearch_mcp_cli.exceptions import ProfileWarmupError


@pytest.fixture
def warmup_tab():
    """Tab mock with properly wired async-context-manager protocol."""
    tab = AsyncMock()
    tab.navigate = AsyncMock()
    tab.evaluate = AsyncMock(return_value={})
    tab.wait_for_load = AsyncMock()
    tab.override_ua = AsyncMock()
    tab.get_cookies = AsyncMock(return_value=[])
    tab.__aenter__ = AsyncMock(return_value=tab)
    tab.__aexit__ = AsyncMock(return_value=None)
    return tab


@pytest.fixture
def warmup_browser(warmup_tab):
    browser = AsyncMock()
    browser.create_tab = MagicMock(return_value=warmup_tab)
    browser.close = AsyncMock()
    return browser


@pytest.mark.asyncio
async def test_warmup_visits_three_pages(warmup_browser, warmup_tab):
    warmup_tab.get_cookies.return_value = [
        {"name": "NID", "value": "abc"},
        {"name": "AEC", "value": "def"},
        {"name": "OGPC", "value": "ghi"},
    ]

    await warmup_profile(warmup_browser)

    assert warmup_tab.navigate.call_count == 3
    calls = [c.args[0] for c in warmup_tab.navigate.call_args_list]
    assert "google.com" in calls[0]
    assert "about.google" in calls[1]
    assert "preferences" in calls[2]


@pytest.mark.asyncio
async def test_warmup_verifies_cookies(warmup_browser, warmup_tab):
    warmup_tab.get_cookies.return_value = [
        {"name": "NID", "value": "abc"},
        {"name": "AEC", "value": "def"},
    ]

    await warmup_profile(warmup_browser)


@pytest.mark.asyncio
async def test_warmup_fails_missing_cookies(warmup_browser, warmup_tab):
    warmup_tab.get_cookies.return_value = [
        {"name": "OGPC", "value": "only_this"},
    ]

    with pytest.raises(ProfileWarmupError, match="Missing cookies"):
        await warmup_profile(warmup_browser)


@pytest.mark.asyncio
async def test_warmup_partial_cookies_fails(warmup_browser, warmup_tab):
    warmup_tab.get_cookies.return_value = [
        {"name": "NID", "value": "abc"},
    ]

    with pytest.raises(ProfileWarmupError, match="AEC"):
        await warmup_profile(warmup_browser)


def test_needs_warmup_no_profile(tmp_path):
    assert needs_warmup(tmp_path / "nonexistent") is True


def test_needs_warmup_empty_profile(tmp_path):
    profile = tmp_path / "profile"
    profile.mkdir()
    assert needs_warmup(profile) is True


def test_needs_warmup_with_marker(tmp_path):
    profile = tmp_path / "profile"
    profile.mkdir()
    (profile / ".warmed_up").touch()
    assert needs_warmup(profile) is False
