"""
Tests for the WaybackSearchEngine class.

Tests cover:
- Initialization and configuration
- URL extraction from queries
- Timestamp formatting
- Snapshot retrieval
- Preview generation
- Full content retrieval
- Rate limiting
- Helper methods
"""

from unittest.mock import Mock, patch
import pytest


class TestWaybackSearchEngineInit:
    """Tests for WaybackSearchEngine initialization."""

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

        engine = WaybackSearchEngine()

        assert engine.max_results == 10
        assert engine.max_snapshots_per_url == 3
        assert engine.language == "English"
        assert engine.closest_only is False
        assert engine.available_api == "https://archive.org/wayback/available"
        assert engine.cdx_api == "https://web.archive.org/cdx/search/cdx"

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

        engine = WaybackSearchEngine(max_results=25)

        assert engine.max_results == 25

    def test_init_with_custom_max_snapshots(self):
        """Initialize with custom max_snapshots_per_url."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine(max_snapshots_per_url=5)

        assert engine.max_snapshots_per_url == 5

    def test_init_with_closest_only(self):
        """Initialize with closest_only mode."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine(closest_only=True)

        assert engine.closest_only is True

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

        mock_llm = Mock()
        engine = WaybackSearchEngine(llm=mock_llm)

        assert engine.llm is mock_llm


class TestExtractUrlsFromQuery:
    """Tests for _extract_urls_from_query method."""

    def test_extract_full_url(self):
        """Extract full URL from query."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine()

        # Note: The regex only captures domain, not path
        urls = engine._extract_urls_from_query(
            "Check https://example.com archive"
        )

        assert len(urls) == 1
        assert urls[0] == "https://example.com"

    def test_extract_multiple_urls(self):
        """Extract multiple URLs from query."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine()

        urls = engine._extract_urls_from_query(
            "https://example.com and https://test.org"
        )

        assert len(urls) == 2

    def test_extract_domain_without_http(self):
        """Extract domain without http prefix."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine()

        urls = engine._extract_urls_from_query("example.com")

        assert len(urls) == 1
        assert urls[0] == "http://example.com"

    def test_extract_partial_url(self):
        """Extract partial URL with path."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine()

        urls = engine._extract_urls_from_query("example.com/page")

        assert len(urls) == 1
        assert urls[0] == "http://example.com/page"

    def test_extract_no_urls_found(self):
        """Return empty when no URLs found."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine()

        # Patch at the langchain_community location since it's imported inside the method
        with patch(
            "langchain_community.utilities.DuckDuckGoSearchAPIWrapper"
        ) as mock_ddg:
            mock_ddg.return_value.results.return_value = []
            urls = engine._extract_urls_from_query("just some text")

        assert urls == []


class TestFormatTimestamp:
    """Tests for _format_timestamp method."""

    def test_format_valid_timestamp(self):
        """Format valid Wayback timestamp."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine()

        formatted = engine._format_timestamp("20240115103045")

        assert formatted == "2024-01-15 10:30:45"

    def test_format_short_timestamp(self):
        """Format short timestamp returns as-is."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine()

        formatted = engine._format_timestamp("2024")

        assert formatted == "2024"


class TestGetWaybackSnapshots:
    """Tests for _get_wayback_snapshots method."""

    def test_get_snapshots_closest_only(self):
        """Get closest snapshot."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "archived_snapshots": {
                "closest": {
                    "url": "https://web.archive.org/web/20240115/https://example.com",
                    "timestamp": "20240115103045",
                    "available": True,
                    "status": "200",
                }
            }
        }

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_wayback.safe_get",
            return_value=mock_response,
        ):
            engine = WaybackSearchEngine(closest_only=True)
            snapshots = engine._get_wayback_snapshots("https://example.com")

            assert len(snapshots) == 1
            assert snapshots[0]["timestamp"] == "20240115103045"
            assert snapshots[0]["original_url"] == "https://example.com"

    def test_get_snapshots_cdx_api(self):
        """Get multiple snapshots via CDX API."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.json.return_value = [
            ["timestamp", "original", "statuscode", "mimetype"],
            ["20240115", "https://example.com", "200", "text/html"],
            ["20230615", "https://example.com", "200", "text/html"],
        ]

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_wayback.safe_get",
            return_value=mock_response,
        ):
            engine = WaybackSearchEngine(closest_only=False)
            snapshots = engine._get_wayback_snapshots("https://example.com")

            assert len(snapshots) == 2
            assert "20240115" in snapshots[0]["timestamp"]

    def test_get_snapshots_rate_limit(self):
        """Get snapshots handles rate limit."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )
        from local_deep_research.web_search_engines.rate_limiting import (
            RateLimitError,
        )

        mock_response = Mock()
        mock_response.status_code = 429

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_wayback.safe_get",
            return_value=mock_response,
        ):
            engine = WaybackSearchEngine(closest_only=True)

            with pytest.raises(RateLimitError):
                engine._get_wayback_snapshots("https://example.com")


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_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine()

        mock_snapshots = [
            {
                "timestamp": "20240115103045",
                "formatted_date": "2024-01-15 10:30:45",
                "url": "https://web.archive.org/web/20240115/https://example.com",
                "original_url": "https://example.com",
            }
        ]

        with patch.object(
            engine,
            "_extract_urls_from_query",
            return_value=["https://example.com"],
        ):
            with patch.object(
                engine, "_get_wayback_snapshots", return_value=mock_snapshots
            ):
                previews = engine._get_previews("https://example.com")

                assert len(previews) == 1
                assert "Archive of" in previews[0]["title"]
                assert previews[0]["original_url"] == "https://example.com"

    def test_get_previews_no_urls(self):
        """Get previews handles no URLs found."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine()

        with patch.object(engine, "_extract_urls_from_query", return_value=[]):
            previews = engine._get_previews("random text")

            assert previews == []


class TestRemoveBoilerplate:
    """Tests for _remove_boilerplate method."""

    def test_remove_boilerplate_empty(self):
        """Remove boilerplate handles empty content."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine()

        result = engine._remove_boilerplate("")

        assert result == ""

    def test_remove_boilerplate_with_content(self):
        """Remove boilerplate processes HTML."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine()

        html = "<html><body><p>Main content here</p></body></html>"

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_wayback.justext.justext"
        ) as mock_justext:
            mock_para = Mock()
            mock_para.text = "Main content here"
            mock_para.is_boilerplate = False
            mock_justext.return_value = [mock_para]

            result = engine._remove_boilerplate(html)

            assert "Main content here" in result


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

    def test_get_full_content_returns_items(self):
        """Get full content returns processed items."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine()

        items = [
            {
                "title": "Test Archive",
                "link": "https://web.archive.org/web/20240115/https://example.com",
            }
        ]

        with patch.object(
            engine,
            "_get_wayback_content",
            return_value=("<html>", "Cleaned content"),
        ):
            results = engine._get_full_content(items)

            assert len(results) == 1
            assert results[0]["full_content"] == "Cleaned content"
            assert results[0]["raw_html"] == "<html>"


class TestSearchByUrl:
    """Tests for search_by_url method."""

    def test_search_by_url(self):
        """Search by URL returns snapshots."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        engine = WaybackSearchEngine()

        mock_snapshots = [
            {
                "timestamp": "20240115103045",
                "formatted_date": "2024-01-15 10:30:45",
                "url": "https://web.archive.org/web/20240115/https://example.com",
                "original_url": "https://example.com",
            }
        ]

        with patch.object(
            engine, "_get_wayback_snapshots", return_value=mock_snapshots
        ):
            with patch.object(
                engine, "_get_full_content", return_value=[{"test": "data"}]
            ):
                results = engine.search_by_url("https://example.com")

                assert len(results) == 1


class TestGetLatestSnapshot:
    """Tests for get_latest_snapshot method."""

    def test_get_latest_snapshot(self):
        """Get latest snapshot returns result."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "archived_snapshots": {
                "closest": {
                    "url": "https://web.archive.org/web/20240115/https://example.com",
                    "timestamp": "20240115103045",
                }
            }
        }

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_wayback.safe_get",
            return_value=mock_response,
        ):
            with patch.object(
                WaybackSearchEngine,
                "_get_wayback_content",
                return_value=("<html>", "Content"),
            ):
                engine = WaybackSearchEngine()
                result = engine.get_latest_snapshot("https://example.com")

                assert result is not None
                assert "20240115103045" in result["timestamp"]

    def test_get_latest_snapshot_not_found(self):
        """Get latest snapshot returns None if not found."""
        from local_deep_research.web_search_engines.engines.search_engine_wayback import (
            WaybackSearchEngine,
        )

        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.json.return_value = {"archived_snapshots": {}}

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_wayback.safe_get",
            return_value=mock_response,
        ):
            engine = WaybackSearchEngine()
            result = engine.get_latest_snapshot("https://nonexistent.com")

            assert result is None


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

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

        assert WaybackSearchEngine.is_public is True
