"""Tests for Direct PDF downloader."""

from unittest.mock import Mock, patch


from local_deep_research.research_library.downloaders.direct_pdf import (
    DirectPDFDownloader,
)


class TestDirectPDFDownloaderInit:
    """Tests for DirectPDFDownloader initialization."""

    def test_initializes_with_default_timeout(self):
        """Should initialize with default timeout."""
        downloader = DirectPDFDownloader()
        assert downloader.timeout == 30

    def test_initializes_with_custom_timeout(self):
        """Should accept custom timeout."""
        downloader = DirectPDFDownloader(timeout=60)
        assert downloader.timeout == 60

    def test_creates_session(self):
        """Should create a requests session."""
        downloader = DirectPDFDownloader()
        assert downloader.session is not None


class TestDirectPDFDownloaderCanHandle:
    """Tests for can_handle method."""

    def test_handles_pdf_url(self):
        """Should handle URLs ending with .pdf."""
        downloader = DirectPDFDownloader()
        assert downloader.can_handle("https://example.com/paper.pdf")
        assert downloader.can_handle("https://example.com/path/to/document.PDF")

    def test_handles_pdf_url_with_query_params(self):
        """Should handle PDF URLs with query parameters."""
        downloader = DirectPDFDownloader()
        assert downloader.can_handle(
            "https://example.com/paper.pdf?token=abc123"
        )

    def test_rejects_non_pdf_urls(self):
        """Should reject non-PDF URLs."""
        downloader = DirectPDFDownloader()
        assert not downloader.can_handle("https://example.com/paper.html")
        assert not downloader.can_handle("https://example.com/document")
        assert not downloader.can_handle("https://arxiv.org/abs/1234.5678")

    def test_rejects_empty_url(self):
        """Should reject empty URLs."""
        downloader = DirectPDFDownloader()
        assert not downloader.can_handle("")


class TestDirectPDFDownloaderDownload:
    """Tests for download method."""

    def test_downloads_pdf_successfully(self, mock_pdf_content):
        """Should download PDF successfully."""
        downloader = DirectPDFDownloader()

        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.content = mock_pdf_content
        mock_response.headers = {"Content-Type": "application/pdf"}
        mock_response.raise_for_status = Mock()

        with patch.object(
            downloader.session, "get", return_value=mock_response
        ):
            result = downloader.download("https://example.com/paper.pdf")

        assert result is not None
        assert result == mock_pdf_content

    def test_handles_download_failure(self):
        """Should handle download failure gracefully."""
        downloader = DirectPDFDownloader()

        with patch.object(
            downloader.session, "get", side_effect=Exception("Network error")
        ):
            result = downloader.download("https://example.com/paper.pdf")

        assert result is None

    def test_handles_404_response(self):
        """Should handle 404 response."""
        downloader = DirectPDFDownloader()

        mock_response = Mock()
        mock_response.status_code = 404
        mock_response.raise_for_status = Mock(
            side_effect=Exception("404 Not Found")
        )

        with patch.object(
            downloader.session, "get", return_value=mock_response
        ):
            result = downloader.download("https://example.com/paper.pdf")

        assert result is None


class TestDirectPDFDownloaderDownloadWithResult:
    """Tests for download_with_result method."""

    def test_returns_download_result_on_success(self, mock_pdf_content):
        """Should return DownloadResult with content on success."""
        downloader = DirectPDFDownloader()

        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.content = mock_pdf_content
        mock_response.headers = {"Content-Type": "application/pdf"}
        mock_response.raise_for_status = Mock()

        with patch.object(
            downloader.session, "get", return_value=mock_response
        ):
            result = downloader.download_with_result(
                "https://example.com/paper.pdf"
            )

        assert result.is_success is True
        assert result.content == mock_pdf_content

    def test_returns_skip_reason_on_failure(self):
        """Should return skip_reason when download fails."""
        downloader = DirectPDFDownloader()

        with patch.object(
            downloader.session, "get", side_effect=Exception("Network error")
        ):
            result = downloader.download_with_result(
                "https://example.com/paper.pdf"
            )

        assert result.is_success is False
        assert result.skip_reason is not None
