"""Tests for the autodebug autonomous analyzer module."""



class TestCategorizeFailure:
    """Tests for failure categorization."""

    def test_categorize_assertion_error(self):
        """Test categorizing AssertionError."""
        from autodebug.autonomous.analyzer import categorize_failure

        category = categorize_failure("AssertionError", "assert 1 == 2")

        assert category is not None
        assert category.name == "assertion_error"
        assert "adjust_assertion" in category.fix_strategies

    def test_categorize_type_error(self):
        """Test categorizing TypeError."""
        from autodebug.autonomous.analyzer import categorize_failure

        category = categorize_failure("TypeError", "'NoneType' object is not subscriptable")

        assert category is not None
        assert category.name == "type_error"

    def test_categorize_attribute_error(self):
        """Test categorizing AttributeError."""
        from autodebug.autonomous.analyzer import categorize_failure

        category = categorize_failure("AttributeError", "'str' object has no attribute 'foo'")

        assert category is not None
        assert category.name == "attribute_error"

    def test_categorize_key_error(self):
        """Test categorizing KeyError."""
        from autodebug.autonomous.analyzer import categorize_failure

        category = categorize_failure("KeyError", "'missing_key'")

        assert category is not None
        assert category.name == "key_error"

    def test_categorize_value_error(self):
        """Test categorizing ValueError."""
        from autodebug.autonomous.analyzer import categorize_failure

        category = categorize_failure("ValueError", "invalid literal for int()")

        assert category is not None
        assert category.name == "value_error"

    def test_categorize_import_error(self):
        """Test categorizing ImportError."""
        from autodebug.autonomous.analyzer import categorize_failure

        category = categorize_failure("ImportError", "No module named 'foo'")

        assert category is not None
        assert category.name == "import_error"

    def test_categorize_unknown_error(self):
        """Test categorizing unknown error type."""
        from autodebug.autonomous.analyzer import categorize_failure

        category = categorize_failure("CustomException", "some error")

        # Should still return something (generic category or None)
        # Behavior depends on implementation


class TestAnalyzeFailure:
    """Tests for failure analysis."""

    def test_analyze_simple_assertion(self):
        """Test analyzing a simple assertion failure."""
        from autodebug.autonomous.analyzer import analyze_failure

        exception = {
            "exc_type": "AssertionError",
            "message": "assert 1 == 2",
            "stack": [
                {
                    "file": "test_example.py",
                    "line": 10,
                    "function": "test_add",
                    "code": "assert result == expected",
                }
            ],
        }

        analysis = analyze_failure(exception)

        assert analysis.exception_type == "AssertionError"
        assert analysis.exception_message == "assert 1 == 2"
        assert len(analysis.stack_trace) == 1
        assert analysis.stack_trace[0].file == "test_example.py"
        assert analysis.stack_trace[0].line == 10
        assert analysis.category is not None

    def test_analyze_with_causal_slice(self):
        """Test analyzing failure with causal slice context."""
        from autodebug.autonomous.analyzer import analyze_failure

        exception = {
            "exc_type": "KeyError",
            "message": "'user_id'",
            "stack": [
                {
                    "file": "handlers.py",
                    "line": 42,
                    "function": "get_user",
                    "code": "return data['user_id']",
                }
            ],
        }

        causal_slice = {
            "last_http": {"url": "http://api.example.com/users", "status": 200},
            "last_sql": {"query": "SELECT * FROM users WHERE id = ?"},
        }

        analysis = analyze_failure(exception, causal_slice=causal_slice)

        assert analysis.exception_type == "KeyError"
        # Causal slice info should be in context
        assert "last_http" in analysis.context or "causal_slice" in str(analysis.context)

    def test_analyze_extracts_stack_frames(self):
        """Test that stack frames are properly extracted."""
        from autodebug.autonomous.analyzer import analyze_failure

        exception = {
            "exc_type": "ValueError",
            "message": "invalid value",
            "stack": [
                {"file": "a.py", "line": 1, "function": "func_a", "code": "call_b()"},
                {"file": "b.py", "line": 2, "function": "func_b", "code": "call_c()"},
                {"file": "c.py", "line": 3, "function": "func_c", "code": "raise ValueError()"},
            ],
        }

        analysis = analyze_failure(exception)

        assert len(analysis.stack_trace) == 3
        assert analysis.stack_trace[0].file == "a.py"
        assert analysis.stack_trace[1].file == "b.py"
        assert analysis.stack_trace[2].file == "c.py"

    def test_analyze_provides_fix_strategies(self):
        """Test that analysis provides fix strategies."""
        from autodebug.autonomous.analyzer import analyze_failure

        exception = {
            "exc_type": "AssertionError",
            "message": "expected True but got False",
            "stack": [
                {"file": "test.py", "line": 5, "function": "test_it", "code": "assert result"}
            ],
        }

        analysis = analyze_failure(exception)

        assert analysis.recommended_strategies is not None
        assert len(analysis.recommended_strategies) > 0


class TestExtractContext:
    """Tests for context extraction."""

    def test_extract_basic_context(self):
        """Test extracting basic context from exception."""
        from autodebug.autonomous.analyzer import extract_context

        exception = {
            "exc_type": "TypeError",
            "message": "unsupported operand type(s)",
            "stack": [
                {"file": "math.py", "line": 10, "function": "add", "code": "return a + b"}
            ],
        }

        context = extract_context(exception)

        assert "exception_type" in context
        assert "exception_message" in context
        assert context["failure_file"] == "math.py"
        assert context["failure_line"] == 10
        assert context["failure_function"] == "add"


class TestFormatAnalysisReport:
    """Tests for analysis report formatting."""

    def test_format_report(self):
        """Test formatting an analysis as a report."""
        from autodebug.autonomous.analyzer import analyze_failure, format_analysis_report

        exception = {
            "exc_type": "AssertionError",
            "message": "assert x == y",
            "stack": [
                {"file": "test.py", "line": 5, "function": "test_equality", "code": "assert x == y"}
            ],
        }

        analysis = analyze_failure(exception)
        report = format_analysis_report(analysis)

        assert isinstance(report, str)
        assert "AssertionError" in report
        assert "test.py" in report
