"""
Tests for the WikinewsSearchEngine class.

Tests cover:
- Initialization and configuration
- Language handling
- Query optimization
- Date range adaptation
- Search result processing
- Snippet cleaning
"""

from datetime import datetime, timedelta, UTC
from unittest.mock import Mock, patch


class TestWikinewsSearchEngineInit:
    """Tests for WikinewsSearchEngine initialization."""

    def test_init_with_defaults(self):
        """Initialize with default values."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        engine = WikinewsSearchEngine()

        assert engine.max_results == 10
        assert engine.lang_code == "en"
        assert engine.adaptive_search is True
        assert engine.search_snippets_only is True
        assert "wikinews.org" in engine.api_url

    def test_init_with_custom_max_results(self):
        """Initialize with custom max_results."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        engine = WikinewsSearchEngine(max_results=25)

        assert engine.max_results == 25

    def test_init_with_language_code(self):
        """Initialize with specific language."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        engine = WikinewsSearchEngine(search_language="german")

        assert engine.lang_code == "de"

    def test_init_with_unsupported_language_defaults_to_english(self):
        """Initialize with unsupported language defaults to English."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        engine = WikinewsSearchEngine(search_language="klingon")

        assert engine.lang_code == "en"

    def test_init_with_time_period_month(self):
        """Initialize with monthly time period."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        engine = WikinewsSearchEngine(time_period="m")

        # from_date should be approximately 30 days ago
        expected_from = datetime.now(UTC) - timedelta(days=30)
        assert abs((engine.from_date - expected_from).total_seconds()) < 60

    def test_init_with_time_period_week(self):
        """Initialize with weekly time period."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        engine = WikinewsSearchEngine(time_period="w")

        expected_from = datetime.now(UTC) - timedelta(days=7)
        assert abs((engine.from_date - expected_from).total_seconds()) < 60

    def test_init_with_adaptive_search_disabled(self):
        """Initialize with adaptive_search disabled."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        engine = WikinewsSearchEngine(adaptive_search=False)

        assert engine.adaptive_search is False

    def test_init_with_llm(self):
        """Initialize with LLM."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        mock_llm = Mock()
        engine = WikinewsSearchEngine(llm=mock_llm)

        assert engine.llm is mock_llm


class TestOptimizeQueryForWikinews:
    """Tests for _optimize_query_for_wikinews method."""

    def test_optimize_query_without_llm(self):
        """Optimize query returns original without LLM."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        engine = WikinewsSearchEngine()

        result = engine._optimize_query_for_wikinews("What is the latest news?")

        assert result == "What is the latest news?"

    def test_optimize_query_with_llm(self):
        """Optimize query uses LLM when available."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        mock_llm = Mock()
        mock_llm.invoke.return_value = Mock(content='{"query": "UK politics"}')

        engine = WikinewsSearchEngine(llm=mock_llm)

        result = engine._optimize_query_for_wikinews(
            "What is happening in UK politics?"
        )

        assert result == "UK politics"

    def test_optimize_query_handles_invalid_json(self):
        """Optimize query handles invalid JSON response."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        mock_llm = Mock()
        mock_llm.invoke.return_value = Mock(content="Invalid response")

        engine = WikinewsSearchEngine(llm=mock_llm)

        result = engine._optimize_query_for_wikinews("Original query")

        # Should return original query on error
        assert result == "Original query"


class TestAdaptDateRangeForQuery:
    """Tests for _adapt_date_range_for_query method."""

    def test_adapt_date_range_short_query_no_change(self):
        """Short queries do not trigger date adaptation."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        mock_llm = Mock()
        engine = WikinewsSearchEngine(llm=mock_llm)
        original_from = engine.from_date

        engine._adapt_date_range_for_query("test")

        # LLM should not be called for short queries
        mock_llm.invoke.assert_not_called()
        assert engine.from_date == original_from

    def test_adapt_date_range_without_llm(self):
        """Date range not adapted without LLM."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        engine = WikinewsSearchEngine()
        original_from = engine.from_date

        engine._adapt_date_range_for_query("this is a longer query for testing")

        assert engine.from_date == original_from

    def test_adapt_date_range_current_events(self):
        """Adapt date range for current events."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        mock_llm = Mock()
        mock_llm.invoke.return_value = Mock(content="CURRENT")

        engine = WikinewsSearchEngine(llm=mock_llm)

        engine._adapt_date_range_for_query(
            "What are the latest developments in Ukraine?"
        )

        # For current events, from_date should be recent
        expected_from = datetime.now(UTC) - timedelta(days=60)
        assert abs((engine.from_date - expected_from).total_seconds()) < 60

    def test_adapt_date_range_historical_events(self):
        """Adapt date range for historical events."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        mock_llm = Mock()
        mock_llm.invoke.return_value = Mock(content="HISTORICAL")

        engine = WikinewsSearchEngine(llm=mock_llm)

        engine._adapt_date_range_for_query(
            "What happened during the 2008 financial crisis?"
        )

        # For historical events, from_date should be datetime.min
        assert engine.from_date.year == 1


class TestFetchSearchResults:
    """Tests for _fetch_search_results method."""

    def test_fetch_search_results_returns_results(self):
        """Fetch search results returns data."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "query": {
                "search": [
                    {
                        "pageid": 1,
                        "title": "Test Article",
                        "snippet": "Test snippet",
                    },
                    {
                        "pageid": 2,
                        "title": "Another Article",
                        "snippet": "More text",
                    },
                ]
            }
        }
        mock_response.raise_for_status = Mock()

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_wikinews.safe_get",
            return_value=mock_response,
        ):
            engine = WikinewsSearchEngine()
            results = engine._fetch_search_results("test query", 0)

            assert len(results) == 2
            assert results[0]["title"] == "Test Article"

    def test_fetch_search_results_handles_error(self):
        """Fetch search results handles errors."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )
        import requests

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_wikinews.safe_get",
            side_effect=requests.exceptions.RequestException(
                "Connection error"
            ),
        ):
            engine = WikinewsSearchEngine()
            results = engine._fetch_search_results("test query", 0)

            assert results == []


class TestProcessSearchResult:
    """Tests for _process_search_result method."""

    def test_process_search_result_valid(self):
        """Process valid search result."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        engine = WikinewsSearchEngine()

        # Mock datetime within range
        now = datetime.now(UTC)
        result = {
            "pageid": 123,
            "title": "Test Article",
            "snippet": "Test snippet content",
            "timestamp": (now - timedelta(days=5)).isoformat() + "Z",
        }

        with patch.object(
            engine,
            "_fetch_full_content_and_pubdate",
            return_value=("Full content with test", now - timedelta(days=5)),
        ):
            processed = engine._process_search_result(result, "test")

            assert processed is not None
            assert processed["title"] == "Test Article"
            assert processed["source"] == "wikinews"

    def test_process_search_result_filtered_by_date(self):
        """Process search result filters by date."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        engine = WikinewsSearchEngine(time_period="d")  # Last day only

        # Result from 10 days ago
        old_date = datetime.now(UTC) - timedelta(days=10)
        result = {
            "pageid": 123,
            "title": "Old Article",
            "snippet": "Old snippet",
            "timestamp": old_date.isoformat() + "Z",
        }

        processed = engine._process_search_result(result, "test")

        assert processed is None  # Filtered out due to date


class TestFetchFullContentAndPubdate:
    """Tests for _fetch_full_content_and_pubdate method."""

    def test_fetch_full_content_returns_data(self):
        """Fetch full content returns content and date."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "query": {
                "pages": {
                    "123": {
                        "extract": "Full article content here",
                        "revisions": [{"timestamp": "2024-01-15T10:30:45Z"}],
                    }
                }
            }
        }
        mock_response.raise_for_status = Mock()

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_wikinews.safe_get",
            return_value=mock_response,
        ):
            engine = WikinewsSearchEngine()
            fallback = datetime.now(UTC)
            content, pub_date = engine._fetch_full_content_and_pubdate(
                123, fallback
            )

            assert content == "Full article content here"
            assert pub_date.year == 2024
            assert pub_date.month == 1
            assert pub_date.day == 15


class TestGetPreviews:
    """Tests for _get_previews method."""

    def test_get_previews_returns_results(self):
        """Get previews returns formatted results."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        engine = WikinewsSearchEngine(max_results=1)

        mock_search_results = [
            {
                "pageid": 1,
                "title": "Article 1",
                "snippet": "Snippet 1",
                "timestamp": "2024-01-15T10:00:00Z",
            }
        ]

        with patch.object(engine, "_adapt_date_range_for_query"):
            with patch.object(
                engine, "_optimize_query_for_wikinews", return_value="test"
            ):
                # Return results first, then empty to break the while loop
                with patch.object(
                    engine,
                    "_fetch_search_results",
                    side_effect=[mock_search_results, []],
                ):
                    with patch.object(
                        engine,
                        "_process_search_result",
                        return_value={
                            "id": 1,
                            "title": "Article 1",
                            "source": "wikinews",
                        },
                    ):
                        previews = engine._get_previews("test query")

                        assert len(previews) == 1

    def test_get_previews_empty_results(self):
        """Get previews handles empty results."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        engine = WikinewsSearchEngine()

        with patch.object(engine, "_adapt_date_range_for_query"):
            with patch.object(
                engine, "_optimize_query_for_wikinews", return_value="test"
            ):
                with patch.object(
                    engine, "_fetch_search_results", return_value=[]
                ):
                    previews = engine._get_previews("test query")

                    assert previews == []


class TestGetFullContent:
    """Tests for _get_full_content method."""

    def test_get_full_content_returns_items_unchanged(self):
        """Get full content returns items unchanged."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        engine = WikinewsSearchEngine()

        items = [{"id": 1, "title": "Article", "full_content": "Content"}]

        results = engine._get_full_content(items)

        # Since content is fetched in _get_previews, this should return as-is
        assert results == items


class TestCleanWikinewsSnippet:
    """Tests for _clean_wikinews_snippet function."""

    def test_clean_snippet_removes_html_tags(self):
        """Clean snippet removes HTML tags."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            _clean_wikinews_snippet,
        )

        result = _clean_wikinews_snippet("<span>Test</span> content")

        assert result == "Test content"
        assert "<span>" not in result

    def test_clean_snippet_unescapes_entities(self):
        """Clean snippet unescapes HTML entities."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            _clean_wikinews_snippet,
        )

        result = _clean_wikinews_snippet("Test &amp; content")

        assert result == "Test & content"

    def test_clean_snippet_handles_empty(self):
        """Clean snippet handles empty input."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            _clean_wikinews_snippet,
        )

        result = _clean_wikinews_snippet("")

        assert result == ""


class TestClassAttributes:
    """Tests for class attributes."""

    def test_is_public(self):
        """WikinewsSearchEngine is marked as public."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        assert WikinewsSearchEngine.is_public is True

    def test_is_news(self):
        """WikinewsSearchEngine is marked as news."""
        from local_deep_research.web_search_engines.engines.search_engine_wikinews import (
            WikinewsSearchEngine,
        )

        assert WikinewsSearchEngine.is_news is True
