"""Tests for MCP interaction tools — TDD Red phase."""

from __future__ import annotations

import json
import sys
from pathlib import Path

import pytest
from textual.widgets import Input, Static, Button

# Ensure test apps are importable
sys.path.insert(0, str(Path(__file__).parent / "apps"))


@pytest.fixture
async def simple_session():
    """Launch a SimpleApp via the server's session manager, yield session_id, then clean up."""
    from simple_app import SimpleApp
    from textual_mcp.server import _session_manager

    session = _session_manager.create_session("test-interact")
    app = SimpleApp()
    await session.launch(app)
    yield "test-interact"
    try:
        await _session_manager.remove_session("test-interact")
    except KeyError:
        pass


@pytest.fixture
async def input_session():
    """Launch an InputApp via the server's session manager, yield session_id, then clean up."""
    from input_app import InputApp
    from textual_mcp.server import _session_manager

    session = _session_manager.create_session("test-input")
    app = InputApp()
    await session.launch(app)
    yield "test-input"
    try:
        await _session_manager.remove_session("test-input")
    except KeyError:
        pass


class TestTextualPress:
    """Tests 9.1–9.3: textual_press simulates key presses."""

    async def test_press_key(self, simple_session):
        """Test 9.1: textual_press with key names simulates key presses."""
        from textual_mcp.server import textual_press

        sid = simple_session
        result = json.loads(await textual_press(session_id=sid, keys=["tab"]))
        assert "focused_after" in result

    async def test_press_updates_focused_widget(self, input_session):
        """Test 9.2: textual_press updates focused widget."""
        from textual_mcp.server import textual_press, _session_manager

        sid = input_session
        session = _session_manager.get_session(sid)

        # Tab into first input
        await textual_press(session_id=sid, keys=["tab"])
        focused1 = session.app.screen.focused
        assert focused1 is not None

        # Tab again to move to next input
        result = json.loads(await textual_press(session_id=sid, keys=["tab"]))
        focused2 = session.app.screen.focused
        assert focused2 is not None
        assert result["focused_after"] is not None

    async def test_press_invalid_session(self):
        """Test 9.3: textual_press with invalid session_id returns error."""
        from textual_mcp.server import textual_press

        result = json.loads(await textual_press(session_id="nonexistent", keys=["tab"]))
        assert "error" in result


class TestTextualClick:
    """Tests 9.4–9.8: textual_click clicks widgets."""

    async def test_click_selector(self, simple_session):
        """Test 9.4: textual_click with CSS selector clicks the widget."""
        from textual_mcp.server import textual_click

        result = json.loads(await textual_click(session_id=simple_session, selector="#btn"))
        assert "widget_clicked" in result

    async def test_click_by_id(self, simple_session):
        """Test 9.5: textual_click with #id selector resolves and clicks widget."""
        from textual_mcp.server import textual_click, _session_manager

        result = json.loads(await textual_click(session_id=simple_session, selector="#text-input"))
        assert result["widget_clicked"] == "#text-input"
        # Input should now be focused
        session = _session_manager.get_session(simple_session)
        focused = session.app.screen.focused
        assert focused is not None
        assert focused.id == "text-input"

    async def test_click_returns_hit_target(self, simple_session):
        """Test 9.6: textual_click returns hit_target info."""
        from textual_mcp.server import textual_click

        result = json.loads(await textual_click(session_id=simple_session, selector="#btn"))
        assert "hit_target" in result

    async def test_click_with_offset(self, simple_session):
        """Test 9.7: textual_click with offset adjusts click position."""
        from textual_mcp.server import textual_click

        result = json.loads(await textual_click(session_id=simple_session, selector="#btn", offset=[1, 0]))
        assert "widget_clicked" in result

    async def test_click_double(self, simple_session):
        """Test 9.8: textual_click with times=2 produces double click."""
        from textual_mcp.server import textual_click

        result = json.loads(await textual_click(session_id=simple_session, selector="#text-input", times=2))
        assert "widget_clicked" in result


class TestTextualTypeText:
    """Tests 9.9–9.11: textual_type_text types into focused input."""

    async def test_type_text(self, input_session):
        """Test 9.9: textual_type_text types characters into focused input."""
        from textual_mcp.server import textual_type_text, textual_click, _session_manager

        await textual_click(session_id=input_session, selector="#name-input")
        result = json.loads(await textual_type_text(session_id=input_session, text="Alice"))
        session = _session_manager.get_session(input_session)
        name_input = session.app.query_one("#name-input", Input)
        assert name_input.value == "Alice"

    async def test_type_text_submit(self, input_session):
        """Test 9.10: textual_type_text with submit=true presses Enter after typing."""
        from textual_mcp.server import textual_type_text, textual_click, _session_manager

        await textual_click(session_id=input_session, selector="#name-input")
        await textual_type_text(session_id=input_session, text="Bob", submit=True)
        session = _session_manager.get_session(input_session)
        output = session.app.query_one("#output", Static)
        content = str(output.content)
        assert "Bob" in content

    async def test_type_text_returns_value(self, input_session):
        """Test 9.11: textual_type_text returns the input value after typing."""
        from textual_mcp.server import textual_type_text, textual_click

        await textual_click(session_id=input_session, selector="#name-input")
        result = json.loads(await textual_type_text(session_id=input_session, text="Charlie"))
        assert result["text_after"] == "Charlie"


class TestTextualHover:
    """Test 9.12: textual_hover moves mouse over target widget."""

    async def test_hover(self, simple_session):
        """Test 9.12: textual_hover moves mouse to target widget."""
        from textual_mcp.server import textual_hover

        result = json.loads(await textual_hover(session_id=simple_session, selector="#btn"))
        assert "widget_under" in result


class TestInteractionIdle:
    """Test 9.13: interaction tools wait for idle after action."""

    async def test_press_waits_for_idle(self, input_session):
        """Test 9.13: interaction tools wait for idle after action (pilot.pause())."""
        from textual_mcp.server import textual_type_text, textual_click, _session_manager

        await textual_click(session_id=input_session, selector="#name-input")
        await textual_type_text(session_id=input_session, text="Idle Test", submit=True)
        session = _session_manager.get_session(input_session)
        output = session.app.query_one("#output", Static)
        content = str(output.content)
        assert "Idle Test" in content
