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

# Add project root to path
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "../../")))

from GramAddict.core.compiler_engine import VLMCompilerEngine


class TestReproCompilerCrash(unittest.TestCase):
    def setUp(self):
        self.device = MagicMock()
        self.compiler = VLMCompilerEngine(self.device)
        self.xml = "<hierarchy><node index='0' resource-id='test_id' /></hierarchy>"

    @patch("GramAddict.core.llm_provider.query_telepathic_llm")
    def test_list_response_crash(self, mock_query):
        """
        Verify that the compiler does NOT crash when the LLM returns a list.
        It should handle it or return None gracefully.
        """
        # Scenario: LLM returns a list of dictionaries (common with some models)
        mock_query.return_value = json.dumps(
            [{"rule_type": "regex", "target_attribute": "resource-id", "pattern": "test.*", "confidence": 0.9}]
        )

        try:
            result = self.compiler.generate_heuristic("test intent", self.xml)
            # If the current code handles lists correctly, this should pass.
            # But the user reported a crash.
            print(f"Result for list of dicts: {result}")
        except Exception as e:
            self.fail(f"Compiler crashed with list of dicts: {e}")

        # Scenario: LLM returns a raw list (not of dicts)
        mock_query.return_value = json.dumps(["pattern", "test.*"])

        try:
            result = self.compiler.generate_heuristic("test intent", self.xml)
            self.assertIsNone(result, "Should return None for invalid list format")
        except Exception as e:
            # THIS is what the user reported: "'list' object has no attribute 'get'"
            # which happens if it tries to call .get() on the list ["pattern", "test.*"]
            self.fail(f"Compiler crashed with raw list: {e}")


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