"""Integration tests — Calculator App E2E via AppSession + Pilot."""

import pytest
from textual.widgets import Digits, Button

from textual_mcp.app_loader import load_app
from textual_mcp.session import AppSession

CALC_PATH = "/Users/jaredmcfarland/Developer/textual_examples/textual/examples/calculator.py"


@pytest.fixture
async def calc_session():
    """Launch calculator in an AppSession, yield, then stop."""
    app = load_app(CALC_PATH)
    session = AppSession("calc-test")
    await session.launch(app, size=(80, 30))
    yield session
    await session.stop()


def _display_value(session: AppSession) -> str:
    """Read the calculator display (Digits#numbers)."""
    return session.app.query_one("#numbers", Digits).value


class TestCalculatorLaunch:
    """Test 11.1: Launch calculator app."""

    @pytest.mark.asyncio
    async def test_launch_calculator(self, calc_session):
        assert calc_session.is_running is True
        assert type(calc_session.app).__name__ == "CalculatorApp"


class TestCalculatorSnapshot:
    """Test 11.2: Widget tree has calculator structure."""

    @pytest.mark.asyncio
    async def test_snapshot_has_buttons(self, calc_session):
        tree = calc_session.serializer.serialize(calc_session.app)
        # Should contain button refs and IDs
        assert "Button#number-1" in tree
        assert "Button#number-9" in tree
        assert "Button#plus" in tree
        assert "Button#equals" in tree
        assert "Digits#numbers" in tree


class TestCalculatorClickNumbers:
    """Test 11.3: Click number buttons and verify display."""

    @pytest.mark.asyncio
    async def test_click_number_updates_display(self, calc_session):
        await calc_session.pilot.click("#number-5")
        await calc_session.pilot.pause()
        assert _display_value(calc_session) == "5"

    @pytest.mark.asyncio
    async def test_click_multiple_numbers(self, calc_session):
        await calc_session.pilot.click("#number-1")
        await calc_session.pilot.click("#number-2")
        await calc_session.pilot.click("#number-3")
        await calc_session.pilot.pause()
        assert _display_value(calc_session) == "123"


class TestCalculatorAddition:
    """Test 11.4: Perform 2 + 3 = 5 via click."""

    @pytest.mark.asyncio
    async def test_addition_2_plus_3(self, calc_session):
        await calc_session.pilot.click("#number-2")
        await calc_session.pilot.click("#plus")
        await calc_session.pilot.click("#number-3")
        await calc_session.pilot.click("#equals")
        await calc_session.pilot.pause()
        assert _display_value(calc_session) == "5"


class TestCalculatorKeyboard:
    """Test 11.5: Perform calculation via keyboard input."""

    @pytest.mark.asyncio
    async def test_keyboard_4_times_5(self, calc_session):
        await calc_session.pilot.press("4")
        await calc_session.pilot.press("asterisk")
        await calc_session.pilot.press("5")
        await calc_session.pilot.press("equals_sign")
        await calc_session.pilot.pause()
        assert _display_value(calc_session) == "20"


class TestCalculatorClear:
    """Test 11.6: AC button clears display."""

    @pytest.mark.asyncio
    async def test_ac_clears(self, calc_session):
        await calc_session.pilot.click("#number-7")
        await calc_session.pilot.click("#number-8")
        await calc_session.pilot.pause()
        assert _display_value(calc_session) == "78"

        await calc_session.pilot.press("c")  # triggers AC
        await calc_session.pilot.pause()
        assert _display_value(calc_session) == "0"


class TestCalculatorDivisionByZero:
    """Test 11.7: Division by zero shows error."""

    @pytest.mark.asyncio
    async def test_division_by_zero(self, calc_session):
        await calc_session.pilot.click("#number-5")
        await calc_session.pilot.click("#divide")
        await calc_session.pilot.click("#number-0")
        await calc_session.pilot.click("#equals")
        await calc_session.pilot.pause()
        assert _display_value(calc_session) == "Error"


class TestCalculatorScreenshot:
    """Test 11.8: Screenshot returns valid SVG."""

    @pytest.mark.asyncio
    async def test_screenshot_svg(self, calc_session):
        svg = calc_session.app.export_screenshot()
        assert svg.startswith("<?xml") or svg.startswith("<svg")
        assert "</svg>" in svg


class TestCalculatorFullWorkflow:
    """Test 11.9: Full workflow — launch, snapshot, interact, verify, stop."""

    @pytest.mark.asyncio
    async def test_full_e2e_workflow(self):
        # Launch
        app = load_app(CALC_PATH)
        session = AppSession("e2e-test")
        await session.launch(app, size=(80, 30))
        assert session.is_running is True

        # Snapshot
        tree = session.serializer.serialize(session.app)
        assert "Button" in tree

        # Interact: 9 - 4 = 5
        await session.pilot.click("#number-9")
        await session.pilot.click("#minus")
        await session.pilot.click("#number-4")
        await session.pilot.click("#equals")
        await session.pilot.pause()
        assert _display_value(session) == "5"

        # Screenshot
        svg = session.app.export_screenshot()
        assert "</svg>" in svg

        # Stop
        await session.stop()
        assert session.is_running is False


class TestCalculatorWidgetQuery:
    """Test 11.10: Query specific widget by CSS selector."""

    @pytest.mark.asyncio
    async def test_query_button_by_selector(self, calc_session):
        btn = calc_session.app.query_one("#number-7", Button)
        assert btn.label.plain == "7"

    @pytest.mark.asyncio
    async def test_query_digits_display(self, calc_session):
        digits = calc_session.app.query_one("#numbers", Digits)
        assert digits.value == "0"

    @pytest.mark.asyncio
    async def test_query_all_number_buttons(self, calc_session):
        buttons = calc_session.app.query(".number")
        assert len(buttons) == 10  # 0-9
