"""
Integration tests for MCP server.

Tests for complete research workflows with realistic mocked data.
"""

from unittest.mock import patch

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 TestSettingsFlow:
    """Tests for settings snapshot creation and override flow."""

    def test_settings_snapshot_created_for_quick_research(self):
        """Verify settings snapshot is created when calling quick_research."""
        from local_deep_research.mcp.server import quick_research

        with patch(
            "local_deep_research.mcp.server.create_settings_snapshot"
        ) as mock_snapshot:
            mock_snapshot.return_value = {"llm.provider": "openai"}
            with patch(
                "local_deep_research.mcp.server.ldr_quick_summary",
                return_value={
                    "summary": "Test",
                    "findings": [],
                    "sources": [],
                    "iterations": 1,
                },
            ):
                result = quick_research(query="test")

        mock_snapshot.assert_called_once()
        assert result["status"] == "success"

    def test_settings_overrides_applied_to_snapshot(self):
        """Verify overrides are passed to create_settings_snapshot."""
        from local_deep_research.mcp.server import quick_research

        with patch(
            "local_deep_research.mcp.server.create_settings_snapshot"
        ) as mock_snapshot:
            mock_snapshot.return_value = {}
            with (
                patch(
                    "local_deep_research.mcp.server.ldr_quick_summary",
                    return_value={
                        "summary": "Test",
                        "findings": [],
                        "sources": [],
                        "iterations": 1,
                    },
                ),
                patch(
                    "local_deep_research.mcp.server._validate_search_engine",
                    side_effect=lambda e: e,
                ),
                patch(
                    "local_deep_research.mcp.server._validate_strategy",
                    side_effect=lambda s: s,
                ),
            ):
                quick_research(
                    query="test",
                    search_engine="wikipedia",
                    strategy="source-based",
                    iterations=3,
                )

        # Check that overrides were passed (last call is from quick_research)
        call_kwargs = mock_snapshot.call_args[1]
        assert "overrides" in call_kwargs
        overrides = call_kwargs["overrides"]
        assert overrides["search.tool"] == "wikipedia"
        assert overrides["search.search_strategy"] == "source-based"
        assert overrides["search.iterations"] == 3

    def test_settings_snapshot_passed_to_api(self):
        """Verify settings snapshot is passed to the API function."""
        from local_deep_research.mcp.server import quick_research

        mock_settings = {"llm.provider": "openai", "search.tool": "wikipedia"}

        with patch(
            "local_deep_research.mcp.server.create_settings_snapshot",
            return_value=mock_settings,
        ):
            with patch(
                "local_deep_research.mcp.server.ldr_quick_summary"
            ) as mock_api:
                mock_api.return_value = {
                    "summary": "Test",
                    "findings": [],
                    "sources": [],
                    "iterations": 1,
                }
                quick_research(query="test query")

        # Verify settings_snapshot was passed to API
        call_kwargs = mock_api.call_args[1]
        assert "settings_snapshot" in call_kwargs
        assert call_kwargs["settings_snapshot"] == mock_settings

    def test_no_overrides_when_no_params(self):
        """Verify no overrides dict when no optional params provided."""
        from local_deep_research.mcp.server import quick_research

        with patch(
            "local_deep_research.mcp.server.create_settings_snapshot"
        ) as mock_snapshot:
            mock_snapshot.return_value = {}
            with patch(
                "local_deep_research.mcp.server.ldr_quick_summary",
                return_value={
                    "summary": "Test",
                    "findings": [],
                    "sources": [],
                    "iterations": 1,
                },
            ):
                quick_research(query="test")  # No optional params

        # Should still be called (with empty overrides or no overrides kwarg)
        mock_snapshot.assert_called_once()


class TestResearchFlowIntegration:
    """Tests for complete research workflows."""

    def test_quick_research_complete_flow(self):
        """Test complete quick_research flow from input to output."""
        from local_deep_research.mcp.server import quick_research

        mock_result = {
            "summary": "Quantum computing uses qubits for computation.",
            "findings": [
                {"phase": "Iteration 1", "content": "Found info about qubits"},
                {
                    "phase": "Iteration 2",
                    "content": "Found info about superposition",
                },
            ],
            "sources": [
                {"title": "Wikipedia", "link": "https://wikipedia.org/quantum"},
            ],
            "iterations": 2,
            "formatted_findings": "## Findings\n\nContent here",
        }

        with patch(
            "local_deep_research.mcp.server.ldr_quick_summary",
            return_value=mock_result,
        ):
            result = quick_research(
                query="What is quantum computing?",
                search_engine="wikipedia",
                iterations=2,
            )

        assert result["status"] == "success"
        assert result["summary"] == mock_result["summary"]
        assert len(result["findings"]) == 2
        assert len(result["sources"]) == 1
        assert result["iterations"] == 2

    def test_detailed_research_complete_flow(self):
        """Test complete detailed_research flow."""
        from local_deep_research.mcp.server import detailed_research

        mock_result = {
            "query": "machine learning applications",
            "research_id": "research-abc-123",
            "summary": "Machine learning has many applications...",
            "findings": [{"content": "Finding 1"}, {"content": "Finding 2"}],
            "sources": [{"title": "Source 1", "link": "https://example.com"}],
            "iterations": 3,
            "formatted_findings": "Formatted content",
            "metadata": {
                "timestamp": "2024-01-15T10:00:00Z",
                "search_tool": "arxiv",
                "strategy": "source-based",
            },
        }

        with patch(
            "local_deep_research.mcp.server.ldr_detailed_research",
            return_value=mock_result,
        ):
            result = detailed_research(
                query="machine learning applications",
                search_engine="arxiv",
                strategy="source-based",
            )

        assert result["status"] == "success"
        assert result["query"] == "machine learning applications"
        assert result["research_id"] == "research-abc-123"
        assert "metadata" in result
        assert result["metadata"]["search_tool"] == "arxiv"

    def test_generate_report_complete_flow(self):
        """Test complete generate_report flow."""
        from local_deep_research.mcp.server import generate_report

        mock_result = {
            "content": "# Research Report\n\n## Introduction\n\nThis report...\n\n## Findings\n\n...",
            "metadata": {
                "generated_at": "2024-01-15T10:00:00Z",
                "query": "climate change",
            },
        }

        with patch(
            "local_deep_research.mcp.server.ldr_generate_report",
            return_value=mock_result,
        ):
            result = generate_report(
                query="climate change impacts",
                searches_per_section=3,
            )

        assert result["status"] == "success"
        assert result["content"].startswith("# Research Report")
        assert "metadata" in result


class TestDiscoveryToolsIntegration:
    """Integration tests for discovery tools."""

    def test_list_strategies_returns_all_expected_strategies(self):
        """Verify list_strategies returns the complete list."""
        from local_deep_research.mcp.server import list_strategies

        result = list_strategies()

        assert result["status"] == "success"
        strategy_names = [s["name"] for s in result["strategies"]]

        # Check for key strategies
        assert "source-based" in strategy_names
        assert "focused-iteration" in strategy_names
        assert "topic-organization" in strategy_names
        assert "langgraph-agent" in strategy_names

    def test_get_configuration_structure(self):
        """Verify get_configuration returns expected structure."""
        from local_deep_research.mcp.server import get_configuration

        result = get_configuration()

        assert result["status"] == "success"
        assert "config" in result

        config = result["config"]
        assert "llm" in config
        assert "search" in config

        # Check LLM config structure
        assert "provider" in config["llm"]
        assert "model" in config["llm"]
        assert "temperature" in config["llm"]

        # Check search config structure
        assert "default_engine" in config["search"]
        assert "default_strategy" in config["search"]
        assert "iterations" in config["search"]


class TestErrorFlowIntegration:
    """Integration tests for error handling flows."""

    def test_quick_research_error_flow(self):
        """Test error handling flow in quick_research."""
        from local_deep_research.mcp.server import quick_research

        with patch(
            "local_deep_research.mcp.server.ldr_quick_summary",
            side_effect=Exception("LLM service unavailable: 503"),
        ):
            result = quick_research(query="test")

        assert result["status"] == "error"
        assert result["error_type"] == "service_unavailable"

    def test_detailed_research_error_flow(self):
        """Test error handling flow in detailed_research."""
        from local_deep_research.mcp.server import detailed_research

        with patch(
            "local_deep_research.mcp.server.ldr_detailed_research",
            side_effect=Exception("Invalid API key"),
        ):
            result = detailed_research(query="test")

        assert result["status"] == "error"
        assert result["error_type"] == "auth_error"

    def test_generate_report_error_flow(self):
        """Test error handling flow in generate_report."""
        from local_deep_research.mcp.server import generate_report

        with patch(
            "local_deep_research.mcp.server.ldr_generate_report",
            side_effect=Exception("Request timeout after 30s"),
        ):
            result = generate_report(query="test")

        assert result["status"] == "error"
        assert "timeout" in result["error"].lower()
        assert result["error_type"] == "timeout"

    def test_analyze_documents_error_flow(self):
        """Test error handling flow in analyze_documents."""
        from local_deep_research.mcp.server import analyze_documents

        with patch(
            "local_deep_research.mcp.server.ldr_analyze_documents",
            side_effect=Exception("Collection 'nonexistent' not found"),
        ):
            result = analyze_documents(
                query="test", collection_name="nonexistent"
            )

        assert result["status"] == "error"
        assert result["error_type"] == "model_not_found"


class TestMultipleCallsIsolation:
    """Tests to verify calls don't interfere with each other."""

    def test_settings_isolation_between_calls(self):
        """Verify settings from one call don't leak to another."""
        from local_deep_research.mcp.server import quick_research

        calls = []

        def capture_call(*args, **kwargs):
            calls.append(kwargs.get("settings_snapshot", {}))
            return {
                "summary": "Test",
                "findings": [],
                "sources": [],
                "iterations": 1,
            }

        with patch(
            "local_deep_research.mcp.server.ldr_quick_summary",
            side_effect=capture_call,
        ):
            # First call with wikipedia
            quick_research(query="test1", search_engine="wikipedia")
            # Second call with arxiv
            quick_research(query="test2", search_engine="arxiv")

        # Each call should have its own settings
        assert len(calls) == 2
        # Settings should be different (or at least both captured)

    def test_error_in_one_call_doesnt_affect_next(self):
        """Verify an error in one call doesn't affect subsequent calls."""
        from local_deep_research.mcp.server import quick_research

        call_count = [0]

        def mock_api(*args, **kwargs):
            call_count[0] += 1
            if call_count[0] == 1:
                raise Exception("First call fails")
            return {
                "summary": "Success",
                "findings": [],
                "sources": [],
                "iterations": 1,
            }

        with patch(
            "local_deep_research.mcp.server.ldr_quick_summary",
            side_effect=mock_api,
        ):
            result1 = quick_research(query="test1")
            result2 = quick_research(query="test2")

        assert result1["status"] == "error"
        assert result2["status"] == "success"
        assert result2["summary"] == "Success"
