import os
import sys
import unittest
from unittest.mock import MagicMock, patch

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../")))

from GramAddict.core.q_nav_graph import QNavGraph
from GramAddict.core.telepathic_engine import TelepathicEngine


class TestTrapEscape(unittest.TestCase):
    @patch("GramAddict.core.q_nav_graph.time.sleep", return_value=None)
    @patch("GramAddict.core.q_nav_graph.random_sleep", return_value=None)
    @patch("GramAddict.core.situational_awareness.SituationalAwarenessEngine.ensure_clear_screen", return_value=False)
    def test_trap_guard_autonomous_ai_escape(self, mock_sae_clear, mock_q_rand_sleep, mock_q_sleep):
        print("Starting TDD: Testing autonomous Trap Escape with semantic bypass...")

        # 1. Setup mocks
        mock_device = MagicMock()
        mock_device.app_id = "com.instagram.android"
        mock_device._get_current_app.return_value = "com.instagram.android"

        trap_xml = "<hierarchy><node resource-id='modal_trap' /></hierarchy>"
        current_xml = [trap_xml]

        # Dynamic dump that changes after click
        def dynamic_dump():
            return current_xml[0]

        def dynamic_click(**kwargs):
            if kwargs.get("obj") and kwargs["obj"].get("semantic") and "done" in kwargs["obj"].get("semantic").lower():
                current_xml[0] = "<html><node text='Reels'/><node text='Home'/></html>"

        mock_device.dump_hierarchy.side_effect = dynamic_dump
        mock_device.click.side_effect = dynamic_click

        nav_graph = QNavGraph(device=mock_device)

        engine = TelepathicEngine.get_instance()
        engine.confirm_click = MagicMock()
        engine.reject_click = MagicMock()

        original_find_best_node = engine.find_best_node

        def spy_find_best_node(xml_hierarchy, intent_description, **kwargs):
            if "tap home tab" in intent_description.lower():
                return None
            return original_find_best_node(xml_hierarchy, intent_description, **kwargs)

        engine.find_best_node = spy_find_best_node
        nav_graph.engine = engine  # explicitly enforce

        # 2. Execute transition
        # Mock engine finds nothing, triggering the final fallback escape
        nav_graph._execute_transition("tap_home_tab", max_retries=1, mock_semantic_engine=engine)

        # 3. Assertions
        # The new SAE/nav_graph behavior explicitly presses BACK when 'tap_home_tab' fails after all retries
        self.assertTrue(mock_device.press.called, "Trap guard did not autonomously press BACK to escape the sub-view!")
        called_key = mock_device.press.call_args_list[0][0][0]
        self.assertEqual(called_key, "back")
        print("TDD SUCCESS: Autonomous Backend fallback confirmed.")


if __name__ == "__main__":
    unittest.main()
