"""
Coverage tests for local_deep_research/mcp/server.py

Focuses on branches NOT covered by existing tests/mcp/test_server.py and
tests/mcp/test_validation.py:
- _classify_error() for each error-type keyword
- _validate_iterations max_val enforcement
- _validate_questions_per_iteration upper bound
- _validate_max_results boundaries
- _validate_temperature boundaries
- _build_settings_overrides with various parameter combinations
- analyze_documents validation (empty collection_name)
- generate_report searches_per_section validation
- list_strategies / get_configuration exception paths
"""

import pytest

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"
)


# ---------------------------------------------------------------------------
# _classify_error
# ---------------------------------------------------------------------------


class TestClassifyError:
    def _classify(self, msg):
        from local_deep_research.mcp.server import _classify_error

        return _classify_error(msg)

    def test_service_unavailable_503(self):
        assert self._classify("503 service error") == "service_unavailable"

    def test_service_unavailable_keyword(self):
        assert self._classify("service unavailable") == "service_unavailable"

    def test_model_not_found_404(self):
        assert self._classify("404 error") == "model_not_found"

    def test_model_not_found_keyword(self):
        assert self._classify("model not found") == "model_not_found"

    def test_auth_error_api_key(self):
        assert self._classify("invalid api key") == "auth_error"

    def test_auth_error_401(self):
        assert self._classify("401 unauthorized") == "auth_error"

    def test_timeout(self):
        assert self._classify("request timed out") == "timeout"

    def test_rate_limit_429(self):
        assert self._classify("429 too many requests") == "rate_limit"

    def test_rate_limit_keyword(self):
        assert self._classify("rate limit exceeded") == "rate_limit"

    def test_connection_error(self):
        assert self._classify("connection refused") == "connection_error"

    def test_validation_error(self):
        assert self._classify("invalid parameter") == "validation_error"

    def test_unknown(self):
        assert self._classify("some random error") == "unknown"


# ---------------------------------------------------------------------------
# _validate_iterations
# ---------------------------------------------------------------------------


class TestValidateIterations:
    def _vi(self, val, max_val=20):
        from local_deep_research.mcp.server import _validate_iterations

        return _validate_iterations(val, max_val)

    def test_none_returns_none(self):
        assert self._vi(None) is None

    def test_valid_value(self):
        assert self._vi(5) == 5

    def test_exceeds_max_raises(self):
        from local_deep_research.mcp.server import ValidationError

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

    def test_zero_raises(self):
        from local_deep_research.mcp.server import ValidationError

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

    def test_negative_raises(self):
        from local_deep_research.mcp.server import ValidationError

        with pytest.raises(ValidationError):
            self._vi(-3)

    def test_non_integer_raises(self):
        from local_deep_research.mcp.server import ValidationError

        with pytest.raises(ValidationError):
            self._vi(2.5)

    def test_exact_max_allowed(self):
        assert self._vi(20, max_val=20) == 20


# ---------------------------------------------------------------------------
# _validate_questions_per_iteration
# ---------------------------------------------------------------------------


class TestValidateQPI:
    def _vqpi(self, val):
        from local_deep_research.mcp.server import (
            _validate_questions_per_iteration,
        )

        return _validate_questions_per_iteration(val)

    def test_none_returns_none(self):
        assert self._vqpi(None) is None

    def test_valid(self):
        assert self._vqpi(3) == 3

    def test_zero_raises(self):
        from local_deep_research.mcp.server import ValidationError

        with pytest.raises(ValidationError):
            self._vqpi(0)

    def test_exceeds_10_raises(self):
        from local_deep_research.mcp.server import ValidationError

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

    def test_exactly_10_allowed(self):
        assert self._vqpi(10) == 10


# ---------------------------------------------------------------------------
# _validate_max_results
# ---------------------------------------------------------------------------


class TestValidateMaxResults:
    def _vmr(self, val):
        from local_deep_research.mcp.server import _validate_max_results

        return _validate_max_results(val)

    def test_valid(self):
        assert self._vmr(10) == 10

    def test_zero_raises(self):
        from local_deep_research.mcp.server import ValidationError

        with pytest.raises(ValidationError):
            self._vmr(0)

    def test_exceeds_100_raises(self):
        from local_deep_research.mcp.server import ValidationError

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

    def test_exactly_100_allowed(self):
        assert self._vmr(100) == 100


# ---------------------------------------------------------------------------
# _validate_temperature
# ---------------------------------------------------------------------------


class TestValidateTemperature:
    def _vt(self, val):
        from local_deep_research.mcp.server import _validate_temperature

        return _validate_temperature(val)

    def test_none_returns_none(self):
        assert self._vt(None) is None

    def test_valid_float(self):
        assert self._vt(0.7) == pytest.approx(0.7)

    def test_below_zero_raises(self):
        from local_deep_research.mcp.server import ValidationError

        with pytest.raises(ValidationError):
            self._vt(-0.1)

    def test_above_two_raises(self):
        from local_deep_research.mcp.server import ValidationError

        with pytest.raises(ValidationError):
            self._vt(2.1)

    def test_boundaries_allowed(self):
        from local_deep_research.mcp.server import _validate_temperature

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

    def test_non_numeric_raises(self):
        from local_deep_research.mcp.server import ValidationError

        with pytest.raises(ValidationError):
            self._vt("hot")


# ---------------------------------------------------------------------------
# _build_settings_overrides
# ---------------------------------------------------------------------------


class TestBuildSettingsOverrides:
    def test_empty_params_returns_empty_dict(self):
        from local_deep_research.mcp.server import _build_settings_overrides

        result = _build_settings_overrides()
        assert result == {}

    def test_iterations_added(self):
        from local_deep_research.mcp.server import _build_settings_overrides

        result = _build_settings_overrides(iterations=3)
        assert result.get("search.iterations") == 3

    def test_temperature_added(self):
        from local_deep_research.mcp.server import _build_settings_overrides

        result = _build_settings_overrides(temperature=0.5)
        assert result.get("llm.temperature") == pytest.approx(0.5)

    def test_qpi_added(self):
        from local_deep_research.mcp.server import _build_settings_overrides

        result = _build_settings_overrides(questions_per_iteration=4)
        assert result.get("search.questions_per_iteration") == 4


# ---------------------------------------------------------------------------
# analyze_documents – empty collection_name
# ---------------------------------------------------------------------------


class TestAnalyzeDocumentsValidation:
    def test_empty_collection_name_returns_error(self):
        from local_deep_research.mcp.server import analyze_documents

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

    def test_whitespace_collection_name_returns_error(self):
        from local_deep_research.mcp.server import analyze_documents

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


# ---------------------------------------------------------------------------
# generate_report – searches_per_section validation
# ---------------------------------------------------------------------------


class TestGenerateReportValidation:
    def test_searches_per_section_zero_returns_error(self):
        from local_deep_research.mcp.server import generate_report

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

    def test_searches_per_section_over_10_returns_error(self):
        from local_deep_research.mcp.server import generate_report

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