"""
Live tests for browser-hybrid.

End-to-end scenarios testing real-world usage patterns.
These require Chrome running with --remote-debugging-port=9222.

Run: LIVE_TESTS=1 pytest tests/test_live.py -v
"""

from __future__ import annotations

import os
import tempfile
import time

import pytest

from browser_hybrid import Browser
from browser_hybrid.errors import ConnectionError

# Skip all tests in this module if no Chrome
# Uses real _check_connection, not mocked
pytestmark = [
    pytest.mark.skipif(
        not os.environ.get("LIVE_TESTS"),
        reason="LIVE_TESTS env var not set",
    ),
    pytest.mark.real_connection_check,
]


@pytest.fixture
def browser():
    """Browser instance for live tests."""
    b = None
    try:
        b = Browser(timeout=30.0)
        yield b
    except ConnectionError:
        pytest.skip("Chrome not running with --remote-debugging-port=9222")
    finally:
        if b:
            try:
                b.close()
            except Exception:
                pass


class TestNavigationLive:
    """Live tests for navigation."""

    def test_navigate_to_example(self, browser):
        """Navigate to example.com."""
        tab = browser.new_tab("https://example.com")
        time.sleep(0.5)

        # Verify URL
        assert "example.com" in tab.url

        # Verify title via JS
        title = browser.evaluate("document.title")
        assert title == "Example Domain"

        browser.close_tab(tab)

    def test_navigate_to_multiple_pages(self, browser):
        """Navigate through multiple pages."""
        # Start at example.com
        tab = browser.new_tab("https://example.com")
        time.sleep(0.5)

        # Navigate to another page
        browser.navigate("https://www.iana.org/domains/reserved")
        time.sleep(0.5)

        # Verify we're on the new page
        title = browser.evaluate("document.title")
        assert "IANA" in title or "domains" in title.lower()

        browser.close_tab(tab)

    def test_wait_for_element(self, browser):
        """Wait for element to appear."""
        # DuckDuckGo has search input
        tab = browser.new_tab("https://duckduckgo.com")
        time.sleep(1.0)

        # Wait for search input
        found = browser.wait_for(selector="input", timeout=5.0)
        assert found

        browser.close_tab(tab)


class TestAccessibilityLive:
    """Live tests for accessibility tree."""

    def test_parse_complex_page(self, browser):
        """Parse accessibility tree of complex page."""
        tab = browser.new_tab("https://example.com")
        time.sleep(0.5)

        tree = browser.accessibility_tree()

        # Should have structure
        assert tree.role in ("RootWebArea", "WebArea", "document")

        # Should have heading
        headings = tree.find_by_role("heading")
        assert len(headings) > 0

        # Should have paragraphs
        paragraphs = tree.find_by_role("paragraph")
        assert len(paragraphs) > 0

        browser.close_tab(tab)

    def test_find_links(self, browser):
        """Find links via accessibility tree."""
        tab = browser.new_tab("https://example.com")
        time.sleep(0.5)

        tree = browser.accessibility_tree()
        links = tree.find_by_role("link")

        # example.com has a link to www.iana.org
        assert len(links) >= 1

        # First link should have URL
        if links:
            assert links[0].url is not None

        browser.close_tab(tab)

    def test_find_interactive(self, browser):
        """Find interactive elements."""
        # DuckDuckGo has search input
        tab = browser.new_tab("https://duckduckgo.com")
        time.sleep(1.0)

        tree = browser.accessibility_tree()
        interactive = tree.find_interactive()

        # Should have form elements
        roles = {el.role for el in interactive}
        assert "textbox" in roles or "button" in roles or "combobox" in roles

        browser.close_tab(tab)


class TestInteractionsLive:
    """Live tests for interactions."""

    def test_click_link(self, browser):
        """Click a link."""
        tab = browser.new_tab("https://example.com")
        time.sleep(0.5)

        # Click "Learn more" link (example.com has this link)
        clicked = browser.click_by_text("Learn more")
        assert clicked, "Link should be found and clicked"

        # Wait for navigation
        time.sleep(2.0)

        # Should have navigated to iana.org
        current_url = browser.evaluate("window.location.href")
        assert "iana.org" in current_url, f"Expected iana.org in URL, got: {current_url}"

        browser.close_tab(tab)

    def test_click_button(self, browser):
        """Click a button via accessibility tree."""
        tab = browser.new_tab("https://duckduckgo.com")
        time.sleep(1.0)

        # Find search input and type
        tree = browser.accessibility_tree()
        search = tree.find_by_role("combobox")
        assert len(search) > 0, "Search input should exist"
        if search:
            result = browser.click(search[0].ref)
            assert result, "Click should succeed"

        browser.close_tab(tab)

    def test_evaluate_javascript(self, browser):
        """Execute various JavaScript."""
        tab = browser.new_tab("https://example.com")
        time.sleep(0.5)

        # Simple expression
        result = browser.evaluate("1 + 1")
        assert result == 2

        # DOM access
        result = browser.evaluate("document.querySelectorAll('p').length")
        assert result >= 0

        # String result
        result = browser.evaluate("document.title")
        assert result == "Example Domain"

        browser.close_tab(tab)


class TestScrenshotLive:
    """Live tests for screenshots."""

    def test_screenshot_png(self, browser):
        """Take PNG screenshot."""
        tab = browser.new_tab("https://example.com")
        time.sleep(0.5)

        with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as f:
            path = f.name

        try:
            result_path = browser.screenshot(path)
            assert os.path.exists(result_path)
            assert os.path.getsize(result_path) > 1000  # At least 1KB

            # Verify it's a PNG
            with open(result_path, "rb") as f:
                header = f.read(8)
                assert header[:4] == b"\x89PNG"

        finally:
            if os.path.exists(path):
                os.unlink(path)

        browser.close_tab(tab)


class TestErrorHandlingLive:
    """Live tests for error handling."""

    def test_invalid_url(self, browser):
        """Handle invalid URL."""
        # Chrome will show an error page, not raise exception
        tab = browser.new_tab("not-a-url")

        # Should still be able to get tree (error page)
        tree = browser.accessibility_tree()
        assert tree is not None

        browser.close_tab(tab)

    def test_nonexistent_element_click(self, browser):
        """Click nonexistent element returns False."""
        tab = browser.new_tab("https://example.com")
        time.sleep(0.5)

        result = browser.click_by_text("XyzzyPlughBazoo")
        assert result is False

        browser.close_tab(tab)


class TestConnectionPoolLive:
    """Live tests for connection pool."""

    def test_connection_persists(self, browser):
        """Connection persists across operations."""
        tab = browser.new_tab("https://example.com")
        time.sleep(0.5)

        # Multiple operations
        for _ in range(5):
            browser.accessibility_tree()
            browser.evaluate("1 + 1")

        # Should still work
        result = browser.evaluate("2 + 2")
        assert result == 4

        browser.close_tab(tab)

    def test_reconnect_after_tab_close(self, browser):
        """Can create new connection after closing tab."""
        # Create and close first tab
        tab1 = browser.new_tab("https://example.com")
        browser.close_tab(tab1)

        # Create second tab
        tab2 = browser.new_tab("https://example.com")

        # Should work fine
        tree = browser.accessibility_tree()
        assert tree is not None

        browser.close_tab(tab2)


class TestFormFillingLive:
    """Live tests for form filling."""

    def test_fill_form(self, browser):
        """Fill form fields."""
        tab = browser.new_tab("https://duckduckgo.com")
        time.sleep(1.0)

        # Fill search field
        tree = browser.accessibility_tree()
        search = tree.find_by_role("combobox")
        if search:
            browser.type_text(search[0].ref, "test query")

        # Verify value was set
        value = browser.evaluate("document.querySelector('input[name=q]')?.value || ''")
        assert "test" in value.lower()

        browser.close_tab(tab)


class TestKeyboardMouseLive:
    """Live tests for keyboard and mouse (v0.2.2+)."""

    def test_type_slowly(self, browser):
        """Type slowly with character-level control."""
        tab = browser.new_tab("https://duckduckgo.com")
        time.sleep(1.0)

        tree = browser.accessibility_tree()
        search = tree.find_by_role("combobox")
        if search:
            browser.click(search[0].ref)
            browser.type_slowly(search[0].ref, "python browser", delay=0.02)

        browser.close_tab(tab)

    def test_press_key_shortcuts(self, browser):
        """Press key combinations with modifiers."""
        tab = browser.new_tab("https://duckduckgo.com")
        time.sleep(1.0)

        tree = browser.accessibility_tree()
        search = tree.find_by_role("combobox")
        if search:
            browser.click(search[0].ref)
            browser.type_text(search[0].ref, "test")
            # Select all with Ctrl+A
            browser.press_key("a", modifiers=["Control"])
            # Delete with Backspace
            browser.press_key("Backspace")

        browser.close_tab(tab)

    def test_hover_and_right_click(self, browser):
        """Test hover and right-click (v0.2.2)."""
        tab = browser.new_tab("https://example.com")
        time.sleep(0.5)

        tree = browser.accessibility_tree()
        links = tree.find_by_role("link")
        if links:
            # Hover
            browser.hover(links[0].ref)
            # Right-click
            browser.click(links[0].ref, button="right")
            # Dismiss context menu
            browser.press_key("Escape")

        browser.close_tab(tab)


class TestWaitConditionsLive:
    """Live tests for wait conditions (v0.2.0+)."""

    def test_wait_for_text(self, browser):
        """Wait for text to appear."""
        tab = browser.new_tab("https://example.com")

        found = browser.wait_for(text="Example Domain", timeout=5.0)
        assert found

        browser.close_tab(tab)

    def test_wait_for_selector(self, browser):
        """Wait for selector."""
        tab = browser.new_tab("https://example.com")

        found = browser.wait_for(selector="p", timeout=5.0)
        assert found

        browser.close_tab(tab)


class TestCookiesLive:
    """Live tests for cookies (v0.2.0+)."""

    def test_set_and_get_cookies(self, browser):
        """Set and get cookies."""
        tab = browser.new_tab("https://example.com")

        # Set cookie
        browser.set_cookies(
            [{"name": "test_cookie_live", "value": "test_value_123", "domain": ".example.com"}]
        )

        # Get cookie
        cookies = browser.get_cookies()
        test = [c for c in cookies if c.get("name") == "test_cookie_live"]
        assert len(test) == 1
        assert test[0]["value"] == "test_value_123"

        browser.close_tab(tab)
