"""
End-to-end integration tests using PtyHarness.

These tests fork a child process with a real PTY and exercise the full
blessed Terminal → BlessedScreen → Application stack.  They are slower
than unit tests so are marked with ``@pytest.mark.pty``.
"""

import sys
import time

import pytest

pytestmark = [
    pytest.mark.pty,
    pytest.mark.skipif(sys.platform == "win32", reason="PTY not available on Windows"),
]

from pyos import Keys
from pyos.testing.pty_harness import PtyHarness


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

class _SimpleActivity:
    """Minimal activity for smoke tests (defined at module level for pickling)."""
    pass


# We import real activities from the demo module
from pyos.examples.demo import (
    DemoMenuActivity,
    ContactsBrowser,
    NotepadDemo,
    ReflexGame,
    DemoApplication,
)


# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------


class TestAppRendersActivity:
    """Start a simple Activity and verify it renders on the pyte screen."""

    def test_demo_menu_renders_title(self):
        with PtyHarness(DemoMenuActivity) as h:
            h.wait_for_text("PyOS Gallery", timeout=5)

    def test_demo_menu_renders_items(self):
        with PtyHarness(DemoMenuActivity) as h:
            h.wait_for_text("Contacts Browser", timeout=5)
            assert h.find_text("Data Dashboard")


class TestKeystrokeNavigation:
    """Send arrow keys and verify the selection moves."""

    def test_arrow_down_changes_selection(self):
        with PtyHarness(DemoMenuActivity) as h:
            h.wait_for_text("PyOS Gallery", timeout=5)
            # First item is "Contacts Browser" - move down to "Data Dashboard"
            h.send_key(Keys.DOWN)
            time.sleep(0.3)
            # The bottom bar shows selection info after ScrollChange
            h.wait_for_text("2/12", timeout=3)


class TestEscPopsActivity:
    """Press ESC in the top-level activity → app shuts down."""

    def test_esc_exits_app(self):
        with PtyHarness(DemoMenuActivity) as h:
            h.wait_for_text("PyOS Gallery", timeout=5)
            h.send_key(Keys.ESC)
            # The child process should exit within a few seconds
            # (shutdown() in __exit__ will handle cleanup)
            time.sleep(1)
            # If we get here without hanging, the test passes


class TestTextInputThroughBlessed:
    """Type characters and verify they appear on screen."""

    def test_typing_appears_on_screen(self):
        with PtyHarness(DemoMenuActivity) as h:
            h.wait_for_text("PyOS Gallery", timeout=5)
            # Navigate to Notepad (item index 2)
            h.send_key(Keys.DOWN)
            h.send_key(Keys.DOWN)
            time.sleep(0.2)
            h.send_key(Keys.ENTER)
            h.wait_for_text("Notepad", timeout=5)
            # Type some text
            h.send_text("hello world")
            h.wait_for_text("hello world", timeout=3)
            # Verify character count updated
            h.wait_for_text("Chars: 11", timeout=3)


class TestTimerFires:
    """Start the ReflexGame, verify the timer-driven display updates."""

    def test_holding_updates_elapsed(self):
        with PtyHarness(DemoMenuActivity) as h:
            h.wait_for_text("PyOS Gallery", timeout=5)
            # Navigate to "Reflex Game" (index 10)
            for _ in range(10):
                h.send_key(Keys.DOWN)
                time.sleep(0.05)
            time.sleep(0.2)
            h.send_key(Keys.ENTER)
            h.wait_for_text("Reflex Game", timeout=5)
            # Press space to start the timer
            h.send_key(ord(" "))
            h.wait_for_text("HOLDING", timeout=3)
            # Wait for the timer to update
            time.sleep(0.5)
            # The elapsed display should have updated (shows "Elapsed: X.Xs")
            h.wait_for_text("Elapsed:", timeout=3)


class TestDemoMenuToExhibit:
    """Navigate from the demo menu into an exhibit and verify it renders."""

    def test_navigate_to_contacts_browser(self):
        with PtyHarness(DemoMenuActivity) as h:
            h.wait_for_text("PyOS Gallery", timeout=5)
            # First item is "Contacts Browser", press Enter
            h.send_key(Keys.ENTER)
            h.wait_for_text("Contacts Browser", timeout=5)
            # Should show the search input label
            h.wait_for_text("Search", timeout=3)

    def test_navigate_and_return(self):
        with PtyHarness(DemoMenuActivity) as h:
            h.wait_for_text("PyOS Gallery", timeout=5)
            h.send_key(Keys.ENTER)
            h.wait_for_text("Contacts Browser", timeout=5)
            # ESC to go back
            h.send_key(Keys.ESC)
            h.wait_for_text("PyOS Gallery", timeout=5)
