"""Tests for agentic fixer async behavior."""

import asyncio
from unittest.mock import AsyncMock, MagicMock, patch

import pytest


class TestGetSimilarFixesAsync:
    """_get_similar_fixes should not block the event loop."""

    @pytest.mark.asyncio
    async def test_search_runs_in_thread(self):
        """search.search() should be dispatched via asyncio.to_thread."""
        from api.ai.agentic_fixer import AgenticFixer

        fixer = AgenticFixer(org_id="org_test")
        fixer._context = {
            "error_type": "AssertionError",
            "error_message": "expected True",
        }

        mock_result = MagicMock()
        mock_result.to_dict.return_value = {"id": "fix_1"}

        mock_search = MagicMock()
        mock_search.search.return_value = [mock_result]

        with patch("api.ai.agentic_fixer.asyncio.to_thread") as mock_to_thread:
            mock_to_thread.return_value = [mock_result]
            with patch(
                "autodebug.llm_first.hybrid_search.HybridFixSearch",
                return_value=mock_search,
            ):
                results = await fixer._get_similar_fixes(limit=3)

        mock_to_thread.assert_called_once()
        # Verify search.search was passed to to_thread
        call_args = mock_to_thread.call_args
        assert call_args.kwargs.get("limit") == 3 or call_args[1].get("limit") == 3

    @pytest.mark.asyncio
    async def test_returns_empty_on_import_error(self):
        """Should return [] if HybridFixSearch cannot be imported."""
        from api.ai.agentic_fixer import AgenticFixer

        fixer = AgenticFixer(org_id="org_test")
        fixer._context = {
            "error_type": "TypeError",
            "error_message": "None is not callable",
        }

        with patch(
            "api.ai.agentic_fixer.asyncio.to_thread",
            side_effect=ImportError("no module"),
        ):
            results = await fixer._get_similar_fixes()

        assert results == []
