from unittest.mock import MagicMock, patch

import pytest

from GramAddict.core.device_facade import DeviceFacade
from GramAddict.core.telepathic_engine import TelepathicEngine


@pytest.fixture
def mock_device():
    device = MagicMock()
    device.app_id = "com.instagram.android"
    # Mock u2 app_current to simulate a notification flicker
    # Hardened detection makes up to 3 calls in the 'still flicker' case
    device.app_current.side_effect = [
        {"package": "com.whatsapp", "activity": ".Main"},
        {"package": "com.whatsapp", "activity": ".Main"},
        {"package": "com.whatsapp", "activity": ".Main"},
    ]
    return device


def test_drift_hardening_flicker_resolution(mock_device):
    """
    Test that _get_current_app performs a single brief retry on foreign packages.
    Current design: one retry, then returns the detected package as-is.
    Recovery from a persistent foreign app is delegated to the SAE.
    """
    # DeviceFacade expects (device_id, app_id, args)
    # We mock u2.connect to avoid actual connection attempts
    with patch("GramAddict.core.device_facade.u2.connect") as mock_connect:
        mock_connect.return_value = mock_device
        facade = DeviceFacade("mock_serial", "com.instagram.android", MagicMock())

    # We need to patch sleep to avoid waiting
    with patch("GramAddict.core.device_facade.sleep"):
        pkg = facade._get_current_app()

    # After one brief retry, WhatsApp is still active.
    # _get_current_app returns it so the SAE can decide the recovery action.
    assert pkg == "com.whatsapp"


def test_structural_guard_prevention():
    """
    Test that structural intents are NOT blacklisted even if drift is reported.
    """
    # Reset singleton or use real instance
    engine = TelepathicEngine.get_instance()

    # Ensure it's not a mock from other tests
    if hasattr(engine, "_blacklist"):
        # Clear current blacklist for test
        if "tap home tab" in engine._blacklist:
            engine._blacklist["tap home tab"] = []

        # Simulate a drift context
        context = {
            "intent": "tap home tab",
            "semantic_string": "description: 'Home', id context: 'feed tab'",
            "x": 100,
            "y": 2000,
        }
        TelepathicEngine._last_click_context = context

        # Trigger rejection
        engine.reject_click("tap home tab")

        # Verify it is NOT in the persistent blacklist
        assert "description: 'Home', id context: 'feed tab'" not in engine._blacklist.get("tap home tab", [])
