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

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


class TestGridHallucination(unittest.TestCase):
    def setUp(self):
        if os.path.exists("telepathic_memory.json"):
            os.remove("telepathic_memory.json")
        if os.path.exists("telepathic_blacklist.json"):
            os.remove("telepathic_blacklist.json")
        self.device = MagicMock()
        self.device.app_id = "com.instagram.android"
        self.device._get_current_app.return_value = "com.instagram.android"

    def test_repro_grid_tap_hallucination(self):
        """
        REPRO TEST: Verifies that a generic fallback 'True' in verify_success
        causes false learning if the UI changed but we didn't actually open a post.
        """
        nav = QNavGraph(self.device)
        TelepathicEngine.get_instance()

        # VLM picked node 8 which was an 'image button'
        fake_node = {
            "x": 100,
            "y": 100,
            "score": 0.85,
            "semantic": "id context: 'image button'",
            "source": "agentic_fallback",
        }

        def mock_find_best_node(xml, intent, **kwargs):
            TelepathicEngine._last_click_context = {
                "intent": intent,
                "semantic_string": fake_node["semantic"],
                "x": fake_node["x"],
                "y": fake_node["y"],
                "timestamp": 12345,
            }
            return fake_node

        with patch.object(TelepathicEngine, "find_best_node", side_effect=mock_find_best_node):
            # Pre-click XML (Explore Grid)
            pre_xml = '<hierarchy><node package="com.instagram.android" content-desc="Explore" /></hierarchy>'
            # Post click XML changes (maybe a modal opens), but NO FEED MARKERS
            post_xml = '<hierarchy><node package="com.instagram.android" content-desc="Something else" /></hierarchy>'

            self.device.dump_hierarchy.side_effect = [
                pre_xml,  # Attempt 1 pre-clearance
                pre_xml,  # Attempt 1 re-acquire context
                post_xml,  # Attempt 1 post-click
                pre_xml,  # Attempt 2 pre-clearance
                pre_xml,  # Attempt 2 re-acquire context
                post_xml,  # Attempt 2 post-click
            ] + [post_xml] * 20

            # Execute transition for explore grid item
            success = nav._execute_transition("tap_explore_grid_item", MagicMock())

            # success can be False or "CONTEXT_LOST" (which is truthy).
            # If it's True, the test detects the bug.
            if success:
                print(
                    "\n[!] BUG REPRODUCED: Bot learned 'image button' as explore grid item even though no post was opened."
                )
                is_buggy = True
            else:
                print("\n[V] VERIFICATION SUCCESSFUL: Bot rejected 'image button' because no post was opened.")
                is_buggy = False

            self.assertFalse(is_buggy, "Should NOT learn mapping if opening post failed.")


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