"""Unit tests for Chat and Research History integration.

Tests verify the integration between chat messages and research history:
- Message links to research history via research_id back-reference
- Content is stored INLINE in chat_messages.content (snapshot
  pattern) — no fetch from research_history at read time

The legacy "fetch content from research_history when chat_messages.content
is NULL" design has been retired.
"""

from unittest.mock import MagicMock, patch
from contextlib import contextmanager


class TestResearchHistoryLinking:
    """Tests for linking chat messages to research history."""

    def test_message_stores_research_id(self):
        """Test that message with research correctly stores research_id."""
        from src.local_deep_research.chat.service import ChatService

        mock_session = MagicMock()
        captured_message = None

        def capture_add(obj):
            nonlocal captured_message
            if hasattr(obj, "research_id"):
                captured_message = obj

        mock_session.add.side_effect = capture_add
        mock_session.commit = MagicMock()

        # Mock session query for getting the session
        mock_chat_session = MagicMock()
        mock_chat_session.id = "test-session-123"
        mock_chat_session.message_count = 0
        mock_session.query.return_value.filter_by.return_value.with_for_update.return_value.first.return_value = mock_chat_session
        mock_session.query.return_value.filter_by.return_value.first.return_value = mock_chat_session

        @contextmanager
        def mock_get_user_db_session(username, password=None):
            yield mock_session

        with patch(
            "src.local_deep_research.chat.service.get_user_db_session",
            mock_get_user_db_session,
        ):
            service = ChatService(username="test_user")

            service.add_message(
                session_id="test-session-123",
                role="assistant",
                content="The research answer (snapshot stored inline).",
                message_type="response",
                research_id="research-abc-123",
            )

        # Verify research_id was stored
        assert captured_message is not None
        assert captured_message.research_id == "research-abc-123"

    def test_message_with_research_id_increments_message_count(self):
        """Test that session message count is incremented when research_id is set."""
        from src.local_deep_research.chat.service import ChatService
        from tests.chat.conftest import setup_query_mock_with_session

        mock_session = MagicMock()
        mock_session.add = MagicMock()
        mock_session.commit = MagicMock()

        mock_chat_session = MagicMock()
        mock_chat_session.id = "test-session-123"
        mock_chat_session.message_count = 0
        setup_query_mock_with_session(mock_session, mock_chat_session)

        @contextmanager
        def mock_get_user_db_session(username, password=None):
            yield mock_session

        with patch(
            "src.local_deep_research.chat.service.get_user_db_session",
            mock_get_user_db_session,
        ):
            service = ChatService(username="test_user")

            service.add_message(
                session_id="test-session-123",
                role="assistant",
                content="An inline-stored answer.",
                message_type="response",
                research_id="research-abc-123",
            )

        # Verify message count was incremented
        assert mock_chat_session.message_count == 1


# TestContentFetchingFromResearchHistory was deleted with the
# inline-content schema: chat_messages.content is now NOT NULL and
# stored inline (snapshot semantics). The "fetch from
# research.report_content when content is NULL" design no longer exists.
#
# TestExtractChatContent was previously also removed when
# extract_chat_content was deleted alongside the report_content
# refactor. research.report_content now stores the synthesized
# answer directly, and chat_messages.content stores its own
# inline snapshot — neither side does extraction at read time.
