"""Tests for context documentation formatter."""

from autodoc_mcp.core.context_formatter import (
    ContextDocumentationFormatter,
    ContextWindowManager,
    DocumentationContext,
    PackageDocumentation,
)


class TestContextDocumentationFormatter:
    """Test context documentation formatter functionality."""

    def setup_method(self):
        """Set up test fixtures."""
        self.formatter = ContextDocumentationFormatter()

    def test_format_primary_package(self):
        """Test formatting primary package documentation."""
        package_info = {
            "name": "test-package",
            "version": "1.0.0",
            "summary": "A test package for testing",
            "description": """
            This is a test package.

            Features:
            • Feature one
            • Feature two
            * Another feature
            - Yet another feature

            Main classes: TestClass, AnotherClass
            Main functions: test_function, another_function

            ```python
            from test_package import TestClass
            obj = TestClass()
            ```
            """,
        }

        docs = self.formatter.format_primary_package(package_info)

        assert docs.name == "test-package"
        assert docs.version == "1.0.0"
        assert docs.relationship == "primary"
        assert docs.why_included == "Requested package"
        assert docs.dependency_level == 0
        assert "A test package for testing" in docs.summary
        assert len(docs.key_features) > 0
        assert "Feature one" in docs.key_features
        assert "Feature two" in docs.key_features
        assert docs.usage_examples is not None

    def test_format_dependency_package(self):
        """Test formatting dependency package documentation."""
        package_info = {
            "name": "dep-package",
            "version": "2.0.0",
            "summary": "A dependency package for testing",
            "description": "Simple dependency with minimal features.",
        }

        docs = self.formatter.format_dependency_package(
            package_info, "primary-package", 1
        )

        assert docs.name == "dep-package"
        assert docs.version == "2.0.0"
        assert docs.relationship == "runtime_dependency"
        assert docs.why_included == "Required by primary-package"
        assert docs.dependency_level == 1

    def test_regex_patterns_dont_crash(self):
        """Test that regex patterns handle various inputs without crashing."""
        test_descriptions = [
            "Simple description with no special characters",
            "Description with • bullet points",
            "Description with * asterisk bullets",
            "Description with - dash bullets",
            "Description with [•*-] character classes that caused issues",
            "Mixed content:\n• Bullet one\n* Bullet two\n- Bullet three",
            "Numbered list:\n1. Item one\n2. Item two\n3. Item three",
            "Code blocks:\n```python\nprint('hello')\n```",
            "Class definitions: class MyClass, class AnotherClass",
            "Function calls: my_function(), another_function(args)",
        ]

        for description in test_descriptions:
            package_info = {
                "name": "test-pkg",
                "version": "1.0.0",
                "summary": "Test",
                "description": description,
            }

            # Should not raise any exceptions
            docs = self.formatter.format_primary_package(package_info)
            assert docs.name == "test-pkg"

    def test_extract_key_features(self):
        """Test key feature extraction from descriptions."""
        description = """
        This package provides:
        • Automatic documentation generation
        • Smart dependency resolution
        • Performance optimization
        * Concurrent processing
        - Error handling

        It supports advanced features like caching and validation.
        """

        features = self.formatter._extract_key_features(description)

        assert len(features) > 0
        assert "Automatic documentation generation" in features
        assert "Smart dependency resolution" in features
        assert "Performance optimization" in features

    def test_extract_main_classes(self):
        """Test class name extraction from descriptions."""
        description = """
        Main classes include:
        - `DocumentationContext` for context management
        - class PackageResolver for resolution
        - The `ContextFormatter` class handles formatting
        """

        classes = self.formatter._extract_main_classes(description)

        assert "DocumentationContext" in classes
        assert "PackageResolver" in classes
        assert "ContextFormatter" in classes

    def test_extract_main_functions(self):
        """Test function name extraction from descriptions."""
        description = """
        Key functions:
        - `format_documentation()` formats docs
        - def resolve_dependencies() resolves deps
        - Call `get_context()` to retrieve context
        - Use .fetch_package() for fetching
        """

        functions = self.formatter._extract_main_functions(description)

        assert "format_documentation" in functions
        assert "resolve_dependencies" in functions
        assert "get_context" in functions
        assert "fetch_package" in functions

    def test_token_estimate(self):
        """Test token estimation for documentation."""
        docs = PackageDocumentation(
            name="test-package",
            version="1.0.0",
            relationship="primary",
            summary="Short summary",
            key_features=["Feature one", "Feature two"],
            main_classes=["ClassOne", "ClassTwo"],
            main_functions=["func_one", "func_two"],
            usage_examples="Simple example code",
            why_included="Test",
            dependency_level=0,
        )

        tokens = docs.token_estimate
        assert tokens > 0
        assert isinstance(tokens, int)


class TestContextWindowManager:
    """Test context window management functionality."""

    def test_fit_to_window_no_truncation_needed(self):
        """Test when context fits within token limits."""
        primary = PackageDocumentation(
            name="primary",
            version="1.0.0",
            relationship="primary",
            summary="Short",
            why_included="Test",
        )

        dep1 = PackageDocumentation(
            name="dep1",
            version="1.0.0",
            relationship="runtime_dependency",
            summary="Short dep",
            why_included="Required",
        )

        context = DocumentationContext(
            primary_package=primary, runtime_dependencies=[dep1]
        )

        # Large token limit - should fit
        result = ContextWindowManager.fit_to_window(context, max_tokens=50000)

        assert len(result.runtime_dependencies) == 1
        assert len(result.truncated_packages) == 0

    def test_fit_to_window_with_truncation(self):
        """Test when context needs truncation to fit."""
        primary = PackageDocumentation(
            name="primary",
            version="1.0.0",
            relationship="primary",
            summary="Primary package summary",
            why_included="Test",
        )

        # Create dependencies with long content
        deps = []
        for i in range(3):
            dep = PackageDocumentation(
                name=f"dep{i}",
                version="1.0.0",
                relationship="runtime_dependency",
                summary="Very long dependency summary " * 50,  # Make it long
                why_included="Required",
            )
            deps.append(dep)

        context = DocumentationContext(
            primary_package=primary, runtime_dependencies=deps
        )

        # Small token limit - should truncate
        result = ContextWindowManager.fit_to_window(context, max_tokens=100)

        # Should keep primary but truncate some dependencies
        assert len(result.runtime_dependencies) < len(deps)
        assert len(result.truncated_packages) > 0
        assert result.token_estimate <= 100


class TestDocumentationContext:
    """Test documentation context model."""

    def test_token_estimate_property(self):
        """Test total token estimation."""
        primary = PackageDocumentation(
            name="primary",
            version="1.0.0",
            relationship="primary",
            summary="Primary summary",
            why_included="Test",
        )

        dep = PackageDocumentation(
            name="dep",
            version="1.0.0",
            relationship="runtime_dependency",
            summary="Dependency summary",
            why_included="Required",
        )

        context = DocumentationContext(
            primary_package=primary, runtime_dependencies=[dep]
        )

        total_tokens = context.token_estimate
        expected_tokens = primary.token_estimate + dep.token_estimate

        assert total_tokens == expected_tokens
        assert total_tokens > 0

    def test_all_packages_property(self):
        """Test all packages property includes all types."""
        primary = PackageDocumentation(
            name="primary",
            version="1.0.0",
            relationship="primary",
            summary="Primary",
            why_included="Test",
        )

        runtime_dep = PackageDocumentation(
            name="runtime",
            version="1.0.0",
            relationship="runtime_dependency",
            summary="Runtime dep",
            why_included="Required",
        )

        dev_dep = PackageDocumentation(
            name="dev",
            version="1.0.0",
            relationship="dev_dependency",
            summary="Dev dep",
            why_included="Development",
        )

        context = DocumentationContext(
            primary_package=primary,
            runtime_dependencies=[runtime_dep],
            dev_dependencies=[dev_dep],
        )

        all_packages = context.all_packages

        assert len(all_packages) == 3
        assert primary in all_packages
        assert runtime_dep in all_packages
        assert dev_dep in all_packages
