"""
Tests for MCP server validation functions.

These tests verify input validation for all MCP tool parameters.
"""

import pytest

# Skip all tests if MCP is not available
try:
    import mcp  # noqa: F401

    MCP_AVAILABLE = True
except ImportError:
    MCP_AVAILABLE = False

pytestmark = pytest.mark.skipif(
    not MCP_AVAILABLE, reason="MCP package not installed"
)


class TestValidationFunctions:
    """Tests for parameter validation helper functions."""

    def test_validate_query_valid(self):
        """Test valid query passes validation."""
        from local_deep_research.mcp.server import _validate_query

        result = _validate_query("What is quantum computing?")
        assert result == "What is quantum computing?"

    def test_validate_query_strips_whitespace(self):
        """Test query is stripped of whitespace."""
        from local_deep_research.mcp.server import _validate_query

        result = _validate_query("  test query  ")
        assert result == "test query"

    def test_validate_query_empty_raises(self):
        """Test empty query raises ValidationError."""
        from local_deep_research.mcp.server import (
            _validate_query,
            ValidationError,
        )

        with pytest.raises(ValidationError, match="cannot be empty"):
            _validate_query("")

    def test_validate_query_whitespace_only_raises(self):
        """Test whitespace-only query raises ValidationError."""
        from local_deep_research.mcp.server import (
            _validate_query,
            ValidationError,
        )

        with pytest.raises(ValidationError, match="cannot be empty"):
            _validate_query("   ")

    def test_validate_query_too_long_raises(self):
        """Test query exceeding max length raises ValidationError."""
        from local_deep_research.mcp.server import (
            _validate_query,
            ValidationError,
        )

        long_query = "x" * 10001
        with pytest.raises(ValidationError, match="exceeds maximum length"):
            _validate_query(long_query)

    def test_validate_query_at_max_length(self):
        """Test query at exactly max length is valid."""
        from local_deep_research.mcp.server import _validate_query

        max_query = "x" * 10000
        result = _validate_query(max_query)
        assert len(result) == 10000

    def test_validate_iterations_valid(self):
        """Test valid iterations pass validation."""
        from local_deep_research.mcp.server import _validate_iterations

        assert _validate_iterations(5) == 5
        assert _validate_iterations(1) == 1
        assert _validate_iterations(20) == 20

    def test_validate_iterations_none_allowed(self):
        """Test None iterations returns None."""
        from local_deep_research.mcp.server import _validate_iterations

        assert _validate_iterations(None) is None

    def test_validate_iterations_zero_raises(self):
        """Test zero iterations raises ValidationError."""
        from local_deep_research.mcp.server import (
            _validate_iterations,
            ValidationError,
        )

        with pytest.raises(ValidationError, match="positive integer"):
            _validate_iterations(0)

    def test_validate_iterations_negative_raises(self):
        """Test negative iterations raises ValidationError."""
        from local_deep_research.mcp.server import (
            _validate_iterations,
            ValidationError,
        )

        with pytest.raises(ValidationError, match="positive integer"):
            _validate_iterations(-5)

    def test_validate_iterations_exceeds_max_raises(self):
        """Test iterations exceeding max raises ValidationError."""
        from local_deep_research.mcp.server import (
            _validate_iterations,
            ValidationError,
        )

        with pytest.raises(ValidationError, match="cannot exceed"):
            _validate_iterations(21, max_val=20)

    def test_validate_iterations_custom_max(self):
        """Test iterations with custom max value."""
        from local_deep_research.mcp.server import (
            _validate_iterations,
            ValidationError,
        )

        assert _validate_iterations(5, max_val=10) == 5
        with pytest.raises(ValidationError, match="cannot exceed 10"):
            _validate_iterations(11, max_val=10)

    def test_validate_questions_per_iteration_valid(self):
        """Test valid questions_per_iteration passes validation."""
        from local_deep_research.mcp.server import (
            _validate_questions_per_iteration,
        )

        assert _validate_questions_per_iteration(3) == 3
        assert _validate_questions_per_iteration(1) == 1
        assert _validate_questions_per_iteration(10) == 10

    def test_validate_questions_per_iteration_none_allowed(self):
        """Test None questions_per_iteration returns None."""
        from local_deep_research.mcp.server import (
            _validate_questions_per_iteration,
        )

        assert _validate_questions_per_iteration(None) is None

    def test_validate_questions_per_iteration_zero_raises(self):
        """Test zero questions_per_iteration raises ValidationError."""
        from local_deep_research.mcp.server import (
            _validate_questions_per_iteration,
            ValidationError,
        )

        with pytest.raises(ValidationError, match="positive integer"):
            _validate_questions_per_iteration(0)

    def test_validate_questions_per_iteration_exceeds_max_raises(self):
        """Test questions_per_iteration exceeding max raises ValidationError."""
        from local_deep_research.mcp.server import (
            _validate_questions_per_iteration,
            ValidationError,
        )

        with pytest.raises(ValidationError, match="cannot exceed 10"):
            _validate_questions_per_iteration(11)

    def test_validate_max_results_valid(self):
        """Test valid max_results passes validation."""
        from local_deep_research.mcp.server import _validate_max_results

        assert _validate_max_results(10) == 10
        assert _validate_max_results(1) == 1
        assert _validate_max_results(100) == 100

    def test_validate_max_results_zero_raises(self):
        """Test zero max_results raises ValidationError."""
        from local_deep_research.mcp.server import (
            _validate_max_results,
            ValidationError,
        )

        with pytest.raises(ValidationError, match="positive integer"):
            _validate_max_results(0)

    def test_validate_max_results_exceeds_max_raises(self):
        """Test max_results exceeding max raises ValidationError."""
        from local_deep_research.mcp.server import (
            _validate_max_results,
            ValidationError,
        )

        with pytest.raises(ValidationError, match="cannot exceed 100"):
            _validate_max_results(101)

    def test_validate_temperature_valid(self):
        """Test valid temperature passes validation."""
        from local_deep_research.mcp.server import _validate_temperature

        assert _validate_temperature(0.7) == 0.7
        assert _validate_temperature(0.0) == 0.0
        assert _validate_temperature(2.0) == 2.0

    def test_validate_temperature_none_allowed(self):
        """Test None temperature returns None."""
        from local_deep_research.mcp.server import _validate_temperature

        assert _validate_temperature(None) is None

    def test_validate_temperature_int_converted_to_float(self):
        """Test integer temperature is converted to float."""
        from local_deep_research.mcp.server import _validate_temperature

        result = _validate_temperature(1)
        assert result == 1.0
        assert isinstance(result, float)

    def test_validate_temperature_negative_raises(self):
        """Test negative temperature raises ValidationError."""
        from local_deep_research.mcp.server import (
            _validate_temperature,
            ValidationError,
        )

        with pytest.raises(ValidationError, match="between 0.0 and 2.0"):
            _validate_temperature(-0.1)

    def test_validate_temperature_exceeds_max_raises(self):
        """Test temperature exceeding max raises ValidationError."""
        from local_deep_research.mcp.server import (
            _validate_temperature,
            ValidationError,
        )

        with pytest.raises(ValidationError, match="between 0.0 and 2.0"):
            _validate_temperature(2.1)


class TestValidationInTools:
    """Tests for validation being applied in tool functions."""

    def test_quick_research_empty_query_returns_error(self):
        """Test quick_research with empty query returns validation error."""
        from local_deep_research.mcp.server import quick_research

        result = quick_research(query="")
        assert result["status"] == "error"
        assert result["error_type"] == "validation_error"
        assert "empty" in result["error"].lower()

    def test_quick_research_invalid_iterations_returns_error(self):
        """Test quick_research with invalid iterations returns validation error."""
        from local_deep_research.mcp.server import quick_research

        result = quick_research(query="Test query", iterations=0)
        assert result["status"] == "error"
        assert result["error_type"] == "validation_error"

    def test_quick_research_iterations_exceeds_max_returns_error(self):
        """Test quick_research with iterations exceeding max returns validation error."""
        from local_deep_research.mcp.server import quick_research

        result = quick_research(query="Test query", iterations=100)
        assert result["status"] == "error"
        assert result["error_type"] == "validation_error"

    def test_detailed_research_empty_query_returns_error(self):
        """Test detailed_research with empty query returns validation error."""
        from local_deep_research.mcp.server import detailed_research

        result = detailed_research(query="   ")
        assert result["status"] == "error"
        assert result["error_type"] == "validation_error"

    def test_generate_report_empty_query_returns_error(self):
        """Test generate_report with empty query returns validation error."""
        from local_deep_research.mcp.server import generate_report

        result = generate_report(query="")
        assert result["status"] == "error"
        assert result["error_type"] == "validation_error"

    def test_generate_report_invalid_searches_per_section(self):
        """Test generate_report with invalid searches_per_section returns error."""
        from local_deep_research.mcp.server import generate_report

        result = generate_report(query="Test query", searches_per_section=0)
        assert result["status"] == "error"
        assert result["error_type"] == "validation_error"

    def test_generate_report_searches_per_section_exceeds_max(self):
        """Test generate_report with searches_per_section exceeding max returns error."""
        from local_deep_research.mcp.server import generate_report

        result = generate_report(query="Test query", searches_per_section=11)
        assert result["status"] == "error"
        assert result["error_type"] == "validation_error"

    def test_analyze_documents_empty_query_returns_error(self):
        """Test analyze_documents with empty query returns validation error."""
        from local_deep_research.mcp.server import analyze_documents

        result = analyze_documents(query="", collection_name="test")
        assert result["status"] == "error"
        assert result["error_type"] == "validation_error"

    def test_analyze_documents_empty_collection_returns_error(self):
        """Test analyze_documents with empty collection returns validation error."""
        from local_deep_research.mcp.server import analyze_documents

        result = analyze_documents(query="Test", collection_name="")
        assert result["status"] == "error"
        assert result["error_type"] == "validation_error"

    def test_analyze_documents_invalid_max_results_returns_error(self):
        """Test analyze_documents with invalid max_results returns error."""
        from local_deep_research.mcp.server import analyze_documents

        result = analyze_documents(
            query="Test", collection_name="test", max_results=0
        )
        assert result["status"] == "error"
        assert result["error_type"] == "validation_error"


class TestErrorClassification:
    """Tests for the _classify_error function."""

    def test_classify_service_unavailable(self):
        """Test 503 error is classified as service_unavailable."""
        from local_deep_research.mcp.server import _classify_error

        assert (
            _classify_error("Error 503: Service unavailable")
            == "service_unavailable"
        )
        assert (
            _classify_error("The server is unavailable")
            == "service_unavailable"
        )

    def test_classify_model_not_found(self):
        """Test 404 error is classified as model_not_found."""
        from local_deep_research.mcp.server import _classify_error

        assert (
            _classify_error("Error 404: Model not found") == "model_not_found"
        )
        assert _classify_error("Resource not found") == "model_not_found"

    def test_classify_auth_error(self):
        """Test auth errors are classified correctly."""
        from local_deep_research.mcp.server import _classify_error

        assert _classify_error("Invalid API key") == "auth_error"
        assert _classify_error("Authentication failed") == "auth_error"
        assert _classify_error("Unauthorized access") == "auth_error"
        assert _classify_error("Error 401: Unauthorized") == "auth_error"

    def test_classify_timeout(self):
        """Test timeout errors are classified correctly."""
        from local_deep_research.mcp.server import _classify_error

        assert _classify_error("Request timeout") == "timeout"
        # "Connection timed out" matches "timed out" check which comes before
        # the "connection" check, so it returns "timeout"
        assert _classify_error("Connection timed out") == "timeout"
        # "Operation timed out" also matches "timed out"
        assert _classify_error("Operation timed out") == "timeout"
        assert _classify_error("A timeout occurred") == "timeout"

    def test_classify_rate_limit(self):
        """Test rate limit errors are classified correctly."""
        from local_deep_research.mcp.server import _classify_error

        assert _classify_error("Rate limit exceeded") == "rate_limit"
        assert _classify_error("Error 429: Too many requests") == "rate_limit"

    def test_classify_connection_error(self):
        """Test connection errors are classified correctly."""
        from local_deep_research.mcp.server import _classify_error

        assert _classify_error("Connection refused") == "connection_error"
        assert (
            _classify_error("Failed to establish connection")
            == "connection_error"
        )

    def test_classify_validation_error(self):
        """Test validation errors are classified correctly."""
        from local_deep_research.mcp.server import _classify_error

        assert _classify_error("Validation failed") == "validation_error"
        assert _classify_error("Invalid parameter") == "validation_error"

    def test_classify_unknown_error(self):
        """Test unknown errors are classified as unknown."""
        from local_deep_research.mcp.server import _classify_error

        assert _classify_error("Some random error") == "unknown"
        assert _classify_error("Unexpected exception") == "unknown"


class TestGetAvailableStrategies:
    """Tests for the get_available_strategies function.

    Note: These tests don't require the MCP package as they test the factory module.
    """

    @pytest.mark.skipif(
        True, reason="Tested in test_search_system_factory.py instead"
    )
    def test_get_available_strategies_returns_list(self):
        """Test get_available_strategies returns a list."""
        pass

    def test_list_strategies_uses_get_available_strategies(self):
        """Test MCP list_strategies tool uses the factory function."""
        from local_deep_research.mcp.server import list_strategies
        from local_deep_research.search_system_factory import (
            get_available_strategies,
        )

        result = list_strategies()
        expected = get_available_strategies(show_all=True)

        assert result["status"] == "success"
        assert result["strategies"] == expected
