"""
Comprehensive tests for the NASA ADS search engine.
Tests initialization, search functionality, and result formatting.

Note: These tests mock HTTP requests to avoid requiring an API key.
"""

import pytest
from unittest.mock import Mock


@pytest.fixture(autouse=True)
def mock_journal_filter(monkeypatch):
    """Mock JournalReputationFilter to avoid LLM initialization."""
    monkeypatch.setattr(
        "local_deep_research.web_search_engines.engines.search_engine_nasa_ads.JournalReputationFilter.create_default",
        Mock(return_value=None),
    )


class TestNasaAdsSearchEngineInit:
    """Tests for NASA ADS search engine initialization."""

    def test_init_default_values(self):
        """Test initialization with default values."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine()

        assert engine.max_results == 25
        assert engine.sort_by == "relevance"
        assert engine.min_citations == 0
        assert engine.include_arxiv is True
        assert engine.is_public is True
        assert engine.is_scientific is True

    def test_init_with_custom_max_results(self):
        """Test initialization with custom max results."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine(max_results=50)
        assert engine.max_results == 50

    def test_init_with_api_key(self):
        """Test initialization with API key."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine(api_key="test_api_key")
        assert engine.api_key == "test_api_key"
        assert "Authorization" in engine.headers
        assert "Bearer test_api_key" in engine.headers["Authorization"]

    def test_init_without_api_key(self):
        """Test initialization without API key."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine()
        assert engine.api_key is None
        assert "Authorization" not in engine.headers

    def test_init_with_sort_by(self):
        """Test initialization with different sort options."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine(sort_by="citation_count")
        assert engine.sort_by == "citation_count"

        engine_date = NasaAdsSearchEngine(sort_by="date")
        assert engine_date.sort_by == "date"

    def test_init_with_min_citations(self):
        """Test initialization with minimum citations filter."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine(min_citations=100)
        assert engine.min_citations == 100

    def test_init_with_publication_date_filter(self):
        """Test initialization with publication date filter."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine(from_publication_date="2023-01-01")
        assert engine.from_publication_date == "2023-01-01"

    def test_init_with_include_arxiv_disabled(self):
        """Test initialization with ArXiv preprints disabled."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine(include_arxiv=False)
        assert engine.include_arxiv is False

    def test_init_ignores_false_string_api_key(self):
        """Test that 'False' string for api_key is treated as None."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine(api_key="False")
        assert engine.api_key is None

    def test_init_ignores_false_string_date(self):
        """Test that 'False' string for from_publication_date is treated as None."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine(from_publication_date="False")
        assert engine.from_publication_date is None

    def test_api_base_url_set(self):
        """Test that API base URL is correctly set."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine()
        assert engine.api_base == "https://api.adsabs.harvard.edu/v1"


class TestNasaAdsEngineType:
    """Tests for NASA ADS engine type identification."""

    def test_engine_type_set(self):
        """Test that engine type is properly set."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine()
        assert (
            "nasa" in engine.engine_type.lower()
            or "ads" in engine.engine_type.lower()
        )

    def test_engine_is_public(self):
        """Test that engine is marked as public."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine()
        assert engine.is_public is True

    def test_engine_is_scientific(self):
        """Test that engine is marked as scientific."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine()
        assert engine.is_scientific is True


class TestNasaAdsSearchExecution:
    """Tests for NASA ADS search execution."""

    @pytest.fixture
    def engine(self):
        """Create a NASA ADS engine with API key."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        return NasaAdsSearchEngine(api_key="test_key", max_results=10)

    def test_get_previews_success(self, engine, monkeypatch):
        """Test successful preview retrieval."""
        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.headers = {}
        mock_response.json = Mock(
            return_value={
                "response": {
                    "numFound": 100,
                    "docs": [
                        {
                            "bibcode": "2023ApJ...123..456A",
                            "title": ["Test Astrophysics Paper"],
                            "author": ["Smith, John", "Doe, Jane"],
                            "year": "2023",
                            "pubdate": "2023-06-15",
                            "abstract": "This is the abstract of the paper.",
                            "citation_count": 25,
                            "pub": "The Astrophysical Journal",
                            "doi": ["10.3847/1538-4357/123456"],
                            "bibstem": ["ApJ"],
                            "keyword": ["stars", "galaxies"],
                        }
                    ],
                }
            }
        )

        monkeypatch.setattr(
            "local_deep_research.web_search_engines.engines.search_engine_nasa_ads.safe_get",
            Mock(return_value=mock_response),
        )

        previews = engine._get_previews("black holes")

        assert len(previews) == 1
        assert previews[0]["title"] == "Test Astrophysics Paper"
        assert previews[0]["year"] == "2023"
        assert "Smith, John" in previews[0]["authors"]
        assert previews[0]["citations"] == 25
        assert previews[0]["journal"] == "The Astrophysical Journal"

    def test_get_previews_empty_results(self, engine, monkeypatch):
        """Test preview retrieval with no results."""
        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.headers = {}
        mock_response.json = Mock(
            return_value={"response": {"numFound": 0, "docs": []}}
        )

        monkeypatch.setattr(
            "local_deep_research.web_search_engines.engines.search_engine_nasa_ads.safe_get",
            Mock(return_value=mock_response),
        )

        previews = engine._get_previews("nonexistent topic xyz123")

        assert previews == []

    def test_get_previews_rate_limit_error(self, engine, monkeypatch):
        """Test that 429 errors raise RateLimitError for retry handling."""
        from local_deep_research.web_search_engines.rate_limiting import (
            RateLimitError,
        )

        mock_response = Mock()
        mock_response.status_code = 429
        mock_response.headers = {}

        monkeypatch.setattr(
            "local_deep_research.web_search_engines.engines.search_engine_nasa_ads.safe_get",
            Mock(return_value=mock_response),
        )

        # Rate limit should raise RateLimitError for base class retry handling
        with pytest.raises(RateLimitError):
            engine._get_previews("test query")

    def test_get_previews_unauthorized_error(self, engine, monkeypatch):
        """Test that 401 errors return empty results."""
        mock_response = Mock()
        mock_response.status_code = 401
        mock_response.headers = {}

        monkeypatch.setattr(
            "local_deep_research.web_search_engines.engines.search_engine_nasa_ads.safe_get",
            Mock(return_value=mock_response),
        )

        previews = engine._get_previews("test query")
        assert previews == []

    def test_get_previews_handles_exception(self, engine, monkeypatch):
        """Test that exceptions are handled gracefully."""
        monkeypatch.setattr(
            "local_deep_research.web_search_engines.engines.search_engine_nasa_ads.safe_get",
            Mock(side_effect=Exception("Network error")),
        )

        previews = engine._get_previews("test query")
        assert previews == []

    def test_get_previews_handles_api_error(self, engine, monkeypatch):
        """Test that API errors return empty results."""
        mock_response = Mock()
        mock_response.status_code = 500
        mock_response.text = "Internal Server Error"
        mock_response.headers = {}

        monkeypatch.setattr(
            "local_deep_research.web_search_engines.engines.search_engine_nasa_ads.safe_get",
            Mock(return_value=mock_response),
        )

        previews = engine._get_previews("test query")
        assert previews == []


class TestNasaAdsFormatDocPreview:
    """Tests for NASA ADS document preview formatting."""

    @pytest.fixture
    def engine(self):
        """Create a NASA ADS engine."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        return NasaAdsSearchEngine(api_key="test_key")

    def test_format_doc_with_doi(self, engine):
        """Test formatting document with DOI URL."""
        doc = {
            "bibcode": "2023ApJ...123..456A",
            "title": ["Test Paper"],
            "author": ["Author One"],
            "year": "2023",
            "pubdate": "2023-01-15",
            "abstract": "Abstract text",
            "citation_count": 10,
            "pub": "ApJ",
            "doi": ["10.1234/test"],
            "bibstem": ["ApJ"],
        }

        preview = engine._format_doc_preview(doc)

        assert preview["title"] == "Test Paper"
        assert preview["link"] == "https://doi.org/10.1234/test"
        assert preview["year"] == "2023"
        assert preview["citations"] == 10

    def test_format_doc_without_doi(self, engine):
        """Test formatting document without DOI falls back to ADS URL."""
        doc = {
            "bibcode": "2023ApJ...123..456A",
            "title": ["Test Paper"],
            "author": [],
            "year": "2023",
            "pubdate": "2023-01-15",
            "citation_count": 0,
        }

        preview = engine._format_doc_preview(doc)

        assert "ui.adsabs.harvard.edu" in preview["link"]
        assert "2023ApJ...123..456A" in preview["link"]

    def test_format_doc_with_many_authors(self, engine):
        """Test formatting document with many authors shows et al."""
        doc = {
            "bibcode": "2023ApJ...123..456A",
            "title": ["Test Paper"],
            "author": [f"Author {i}" for i in range(10)],
            "year": "2023",
            "pubdate": "2023-01-15",
            "citation_count": 0,
        }

        preview = engine._format_doc_preview(doc)

        assert "et al." in preview["authors"]

    def test_format_doc_with_arxiv(self, engine):
        """Test formatting ArXiv preprint."""
        doc = {
            "bibcode": "2023arXiv230112345B",
            "title": ["ArXiv Paper"],
            "author": ["Test Author"],
            "year": "2023",
            "pubdate": "2023-01-15",
            "citation_count": 5,
            "bibstem": ["arXiv"],
        }

        preview = engine._format_doc_preview(doc)

        assert preview["is_arxiv"] is True

    def test_format_doc_with_keywords(self, engine):
        """Test formatting document with keywords."""
        doc = {
            "bibcode": "2023ApJ...123..456A",
            "title": ["Test Paper"],
            "author": ["Test Author"],
            "year": "2023",
            "pubdate": "2023-01-15",
            "citation_count": 0,
            "keyword": [
                "black holes",
                "quasars",
                "cosmology",
                "dark matter",
                "galaxies",
                "stars",
            ],
        }

        preview = engine._format_doc_preview(doc)

        # Should limit to 5 keywords
        assert len(preview["keywords"]) == 5

    def test_format_doc_missing_title(self, engine):
        """Test formatting document with missing title."""
        doc = {
            "bibcode": "2023ApJ...123..456A",
            "author": ["Test Author"],
            "year": "2023",
        }

        preview = engine._format_doc_preview(doc)

        assert preview["title"] == "No title"


class TestNasaAdsFullContent:
    """Tests for NASA ADS full content retrieval."""

    def test_get_full_content_returns_results(self):
        """Test that full content returns processed results."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        engine = NasaAdsSearchEngine(api_key="test_key")

        items = [
            {
                "title": "Test Paper",
                "link": "https://doi.org/10.1234/test",
                "snippet": "Test snippet",
                "abstract": "Full abstract text",
                "authors": "John Doe",
                "year": "2023",
                "journal": "ApJ",
                "citations": 50,
                "is_arxiv": False,
                "keywords": ["black holes"],
            }
        ]

        results = engine._get_full_content(items)

        assert len(results) == 1
        assert results[0]["title"] == "Test Paper"
        assert results[0]["content"] == "Full abstract text"
        assert results[0]["metadata"]["authors"] == "John Doe"
        assert results[0]["metadata"]["year"] == "2023"
        assert results[0]["metadata"]["is_arxiv"] is False


class TestNasaAdsFilterSettings:
    """Tests for NASA ADS filter and settings configuration."""

    def test_api_key_from_settings_snapshot(self, monkeypatch):
        """Test that api_key can be loaded from settings snapshot."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        settings = {"search.engine.web.nasa_ads.api_key": "settings_api_key"}

        def mock_get_setting(key, settings_snapshot=None, default=None):
            return settings.get(key, default)

        monkeypatch.setattr(
            "local_deep_research.config.search_config.get_setting_from_snapshot",
            mock_get_setting,
        )

        engine = NasaAdsSearchEngine(settings_snapshot=settings)
        assert engine.api_key == "settings_api_key"

    def test_journal_reputation_filter_integration(self, monkeypatch):
        """Test that journal reputation filter is created when available."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        # Create a mock filter to be returned
        mock_filter = Mock()
        monkeypatch.setattr(
            "local_deep_research.web_search_engines.engines.search_engine_nasa_ads.JournalReputationFilter.create_default",
            Mock(return_value=mock_filter),
        )

        engine = NasaAdsSearchEngine(api_key="test_key")

        # Verify engine was created successfully
        assert engine is not None
        # When filter is returned, it should be in the filters list
        assert mock_filter in engine._content_filters


class TestNasaAdsQueryBuilding:
    """Tests for NASA ADS query building with filters."""

    @pytest.fixture
    def engine_with_filters(self):
        """Create a NASA ADS engine with various filters."""
        from local_deep_research.web_search_engines.engines.search_engine_nasa_ads import (
            NasaAdsSearchEngine,
        )

        return NasaAdsSearchEngine(
            api_key="test_key",
            min_citations=10,
            from_publication_date="2020-01-01",
            include_arxiv=False,
        )

    def test_filters_applied_correctly(self, engine_with_filters):
        """Test that filters are properly set."""
        assert engine_with_filters.min_citations == 10
        assert engine_with_filters.from_publication_date == "2020-01-01"
        assert engine_with_filters.include_arxiv is False
