"""
Behavioral tests that source saving failure does not crash research.

The service itself re-raises exceptions (keeping error handling honest).
The callers in research_service.py wrap source saving in try/except so
a failure doesn't prevent the report from being saved.
"""

import pytest
from contextlib import contextmanager
from unittest.mock import Mock, patch

from local_deep_research.database.session_context import DatabaseSessionError
from local_deep_research.web.services.research_sources_service import (
    ResearchSourcesService,
)

_SERVICE_MOD = "local_deep_research.web.services.research_sources_service"


@contextmanager
def _mock_db_session(mock_session=None):
    """Context manager that yields a mock session."""
    yield mock_session or Mock()


class TestSourceSavingNonFatal:
    """Source saving failure should not prevent report from being saved."""

    def test_service_raises_on_db_session_error(self):
        """Service re-raises DatabaseSessionError (callers decide if fatal)."""

        def _raise(*args, **kwargs):
            raise DatabaseSessionError("no password")

        with patch(f"{_SERVICE_MOD}.get_user_db_session", side_effect=_raise):
            with pytest.raises(DatabaseSessionError):
                ResearchSourcesService.save_research_sources(
                    "test-id",
                    [{"url": "https://example.com", "title": "Test"}],
                    username="testuser",
                )

    def test_returns_zero_on_empty_sources(self):
        """Empty sources list returns 0 without touching the database."""
        # No need to mock anything — empty list triggers early return
        result = ResearchSourcesService.save_research_sources(
            "test-id", [], username="testuser"
        )
        assert result == 0

    def test_saves_sources_and_returns_count(self):
        """With a working session, saves sources and returns count."""
        mock_session = Mock()
        mock_query = Mock()
        mock_query.count.return_value = 0  # No existing resources
        mock_query.filter_by.return_value = mock_query
        mock_session.query.return_value = mock_query

        with patch(
            f"{_SERVICE_MOD}.get_user_db_session",
            return_value=_mock_db_session(mock_session),
        ):
            result = ResearchSourcesService.save_research_sources(
                "test-id",
                [
                    {"url": "https://example.com/1", "title": "Source 1"},
                    {"url": "https://example.com/2", "title": "Source 2"},
                ],
                username="testuser",
            )

        assert result == 2
        assert mock_session.add.call_count == 2
        mock_session.commit.assert_called_once()
