"""
Tests for auto_convert_research module-level function.
"""

import uuid
from contextlib import contextmanager
from unittest.mock import patch

import pytest

from local_deep_research.database.models.library import (
    Collection,
    Document,
    SourceType,
)
from local_deep_research.database.models.research import ResearchHistory
from local_deep_research.research_library.search.services.research_history_indexer import (
    auto_convert_research,
)

INDEXER_MODULE = "local_deep_research.research_library.search.services.research_history_indexer"


@pytest.fixture
def _seed_source_types(library_session):
    """Create the research_report SourceType."""
    report_type = SourceType(
        id=str(uuid.uuid4()),
        name="research_report",
        display_name="Research Report",
        description="Research report documents",
        icon="fas fa-file-alt",
    )
    library_session.add(report_type)
    library_session.commit()
    return report_type


@pytest.fixture
def _seed_collection(library_session):
    """Create the Research History collection."""
    collection = Collection(
        id=str(uuid.uuid4()),
        name="Research History",
        description="Auto-indexed research history",
        is_default=False,
        collection_type="research_history",
    )
    library_session.add(collection)
    library_session.commit()
    return collection


@pytest.fixture
def completed_research(library_session):
    """Create a completed research entry."""
    research = ResearchHistory(
        id=str(uuid.uuid4()),
        query="Test auto-convert",
        mode="detailed_report",
        status="completed",
        created_at="2025-06-01T10:00:00",
        report_content="# Auto-Convert Report\n\nContent here.",
        title="Auto-Convert Test",
    )
    library_session.add(research)
    library_session.commit()
    return research


@pytest.fixture
def mock_session(library_session):
    """Mock get_user_db_session at the indexer module level."""

    @contextmanager
    def _ctx(*args, **kwargs):
        yield library_session

    with patch(f"{INDEXER_MODULE}.get_user_db_session", _ctx):
        yield library_session


class TestAutoConvertResearch:
    def test_converts_completed_research(
        self,
        mock_session,
        completed_research,
        _seed_source_types,
        _seed_collection,
    ):
        """auto_convert_research should create a Document for a completed entry."""
        with patch(
            f"{INDEXER_MODULE}.ensure_research_history_collection",
            return_value=_seed_collection.id,
        ):
            auto_convert_research("testuser", completed_research.id)

        docs = (
            mock_session.query(Document)
            .filter(Document.research_id == completed_research.id)
            .all()
        )
        assert len(docs) == 1

    def test_does_not_raise_on_missing_research(
        self, mock_session, _seed_collection
    ):
        """auto_convert_research should not raise for a non-existent ID."""
        with patch(
            f"{INDEXER_MODULE}.ensure_research_history_collection",
            return_value=_seed_collection.id,
        ):
            # Should not raise — errors are caught and logged
            auto_convert_research("testuser", "nonexistent-id")

    def test_does_not_raise_on_exception(self, library_session):
        """auto_convert_research should catch and log any exception."""
        with patch(
            f"{INDEXER_MODULE}.get_user_db_session",
            side_effect=RuntimeError("DB down"),
        ):
            # Should not raise
            auto_convert_research("testuser", "any-id")

    def test_passes_db_password(self, mock_session, _seed_collection):
        """auto_convert_research should forward db_password to the indexer."""
        with patch(
            f"{INDEXER_MODULE}.ensure_research_history_collection",
            return_value=_seed_collection.id,
        ) as mock_ensure:
            auto_convert_research(
                "testuser", "nonexistent-id", db_password="secret"
            )
            mock_ensure.assert_called_once_with("testuser", "secret")
