"""
TDD: test_browser_remote_cdp.py
browser.py의 --remote-cdp 옵션에 대한 테스트 스위트
"""

import sys
from pathlib import Path
from unittest.mock import AsyncMock, MagicMock, patch

import pytest

# scripts 디렉토리를 path에 추가
sys.path.insert(0, str(Path(__file__).parent.parent))

from browser import build_parser, get_page  # pyright: ignore[reportMissingImports]

# ────────────────────────────────────────────────────────
# argparse --remote-cdp 옵션 테스트
# ────────────────────────────────────────────────────────


def test_remote_cdp_option_exists():
    """build_parser에 --remote-cdp 옵션이 있어야 함"""
    parser = build_parser()
    # help 옵션으로 인해 SystemExit 발생 방지
    with pytest.raises(SystemExit):
        parser.parse_args(["--help"])

    # --remote-cdp 옵션이 있는지 확인
    args = parser.parse_args(["--remote-cdp", "http://localhost:9222", "navigate", "https://example.com"])
    assert hasattr(args, "remote_cdp")
    assert args.remote_cdp == "http://localhost:9222"


def test_remote_cdp_default_is_none():
    """--remote-cdp 기본값이 None이어야 함"""
    parser = build_parser()
    args = parser.parse_args(["navigate", "https://example.com"])
    assert args.remote_cdp is None


def test_remote_cdp_accepts_url():
    """--remote-cdp가 URL 형식의 값을 받아들여야 함"""
    parser = build_parser()
    test_url = "http://100.116.204.95:9222"
    args = parser.parse_args(["--remote-cdp", test_url, "navigate", "https://example.com"])
    assert args.remote_cdp == test_url


def test_remote_cdp_works_with_other_options():
    """--remote-cdp가 다른 옵션과 함께 사용될 수 있어야 함"""
    parser = build_parser()
    args = parser.parse_args(
        [
            "--remote-cdp",
            "http://localhost:9222",
            "navigate",
            "https://example.com",
            "--timeout",
            "30000",
            "--viewport",
            "1920x1080",
        ]
    )
    assert args.remote_cdp == "http://localhost:9222"
    assert args.timeout == 30000
    assert args.viewport == "1920x1080"


# ────────────────────────────────────────────────────────
# get_page() remote_cdp 처리 테스트
# ────────────────────────────────────────────────────────


@pytest.mark.asyncio
async def test_get_page_uses_remote_cdp_when_provided():
    """remote_cdp가 제공되면 원격 CDP에 연결해야 함"""
    # Mock args
    args = MagicMock()
    args.remote_cdp = "http://100.116.204.95:9222"
    args.timeout = 10000
    args.viewport = "1280x720"
    args.stealth = False
    args.block_resources = False

    # Mock playwright
    mock_pw = MagicMock()
    mock_browser = AsyncMock()
    mock_context = AsyncMock()
    mock_page = AsyncMock()

    # Setup mock chain
    mock_pw.chromium.connect_over_cdp = AsyncMock(return_value=mock_browser)
    mock_browser.contexts = [mock_context]
    mock_context.pages = [mock_page]
    mock_page.set_default_timeout = MagicMock()
    mock_page.set_viewport_size = AsyncMock()

    # Call get_page
    browser, page = await get_page(mock_pw, args)

    # Verify connect_over_cdp was called with remote URL
    mock_pw.chromium.connect_over_cdp.assert_called_once_with("http://100.116.204.95:9222")

    # Verify page was returned
    assert page == mock_page


@pytest.mark.asyncio
async def test_get_page_creates_new_context_if_no_contexts():
    """원격 브라우저에 컨텍스트가 없으면 새로 생성해야 함"""
    args = MagicMock()
    args.remote_cdp = "http://localhost:9222"
    args.timeout = 10000
    args.viewport = "1280x720"
    args.stealth = False
    args.block_resources = False

    mock_pw = MagicMock()
    mock_browser = AsyncMock()
    mock_context = AsyncMock()
    mock_page = AsyncMock()

    mock_pw.chromium.connect_over_cdp = AsyncMock(return_value=mock_browser)
    mock_browser.contexts = []  # No existing contexts
    mock_browser.new_context = AsyncMock(return_value=mock_context)
    mock_context.pages = [mock_page]
    mock_page.set_default_timeout = MagicMock()
    mock_page.set_viewport_size = AsyncMock()

    browser, page = await get_page(mock_pw, args)

    # Verify new_context was called
    mock_browser.new_context.assert_called_once()
    assert page == mock_page


@pytest.mark.asyncio
async def test_get_page_creates_new_page_if_no_pages():
    """컨텍스트에 페이지가 없으면 새로 생성해야 함"""
    args = MagicMock()
    args.remote_cdp = "http://localhost:9222"
    args.timeout = 10000
    args.viewport = "1280x720"
    args.stealth = False
    args.block_resources = False

    mock_pw = MagicMock()
    mock_browser = AsyncMock()
    mock_context = AsyncMock()
    mock_page = AsyncMock()

    mock_pw.chromium.connect_over_cdp = AsyncMock(return_value=mock_browser)
    mock_browser.contexts = [mock_context]
    mock_context.pages = []  # No existing pages
    mock_context.new_page = AsyncMock(return_value=mock_page)
    mock_page.set_default_timeout = MagicMock()
    mock_page.set_viewport_size = AsyncMock()

    browser, page = await get_page(mock_pw, args)

    # Verify new_page was called
    mock_context.new_page.assert_called_once()
    assert page == mock_page


@pytest.mark.asyncio
async def test_get_page_applies_block_resources_when_enabled():
    """block_resources가 활성화되면 리소스 차단을 적용해야 함"""
    args = MagicMock()
    args.remote_cdp = "http://localhost:9222"
    args.timeout = 10000
    args.viewport = "1280x720"
    args.stealth = False
    args.block_resources = True

    mock_pw = MagicMock()
    mock_browser = AsyncMock()
    mock_context = AsyncMock()
    mock_page = AsyncMock()

    mock_pw.chromium.connect_over_cdp = AsyncMock(return_value=mock_browser)
    mock_browser.contexts = [mock_context]
    mock_context.pages = [mock_page]
    mock_page.set_default_timeout = MagicMock()
    mock_page.set_viewport_size = AsyncMock()
    mock_page.route = AsyncMock()

    browser, page = await get_page(mock_pw, args)

    # Verify route was called for resource blocking
    mock_page.route.assert_called_once()
    assert page == mock_page


@pytest.mark.asyncio
async def test_get_page_uses_local_chrome_when_no_remote_cdp():
    """remote_cdp가 없으면 기존 로컬 Chrome 로직을 사용해야 함"""
    args = MagicMock()
    args.remote_cdp = None  # No remote CDP
    args.timeout = 10000
    args.viewport = "1280x720"
    args.stealth = False
    args.block_resources = False

    mock_pw = MagicMock()

    # Mock load_session to return None (no existing session)
    with patch("browser.load_session", return_value=None):
        with patch("browser.launch_chrome", return_value=12345):
            with patch("browser.save_session"):
                mock_browser = AsyncMock()
                mock_context = AsyncMock()
                mock_page = AsyncMock()

                mock_pw.chromium.connect_over_cdp = AsyncMock(return_value=mock_browser)
                mock_browser.contexts = []
                mock_browser.new_context = AsyncMock(return_value=mock_context)
                mock_context.pages = []
                mock_context.new_page = AsyncMock(return_value=mock_page)
                mock_page.set_default_timeout = MagicMock()
                mock_page.set_viewport_size = AsyncMock()

                browser, page = await get_page(mock_pw, args)

                # Verify connect_over_cdp was called with local address
                mock_pw.chromium.connect_over_cdp.assert_called_once()
                call_arg = mock_pw.chromium.connect_over_cdp.call_args[0][0]
                assert "127.0.0.1" in call_arg
