"""Testes para o servico LLM."""

from unittest.mock import MagicMock, patch

import pytest

from services.llm_service import LLMResponse, LLMService, get_llm_service


class TestLLMResponse:
    """Testes do modelo LLMResponse."""

    def test_create_response(self) -> None:
        """Deve criar resposta com campos obrigatorios."""
        response = LLMResponse(text="Resposta teste", model="gemini-flash")

        assert response.text == "Resposta teste"
        assert response.model == "gemini-flash"
        assert response.tokens_prompt is None
        assert response.tokens_completion is None

    def test_create_response_with_tokens(self) -> None:
        """Deve criar resposta com contagem de tokens."""
        response = LLMResponse(
            text="Resposta",
            model="gemini-flash",
            tokens_prompt=100,
            tokens_completion=50,
            tokens_total=150,
        )

        assert response.tokens_prompt == 100
        assert response.tokens_completion == 50
        assert response.tokens_total == 150


class TestLLMService:
    """Testes da classe LLMService."""

    def test_init_with_env_var(self) -> None:
        """Deve inicializar com variavel de ambiente."""
        with patch("services.llm_service.OpenRouter") as mock_openrouter:
            mock_openrouter.return_value = MagicMock()
            service = LLMService()

            assert service.api_key == "test-openrouter-key"
            assert service.default_model == "gemini-flash"

    def test_init_with_explicit_key(self) -> None:
        """Deve aceitar API key explicita."""
        with patch("services.llm_service.OpenRouter") as mock_openrouter:
            mock_openrouter.return_value = MagicMock()
            service = LLMService(api_key="custom-key")

            assert service.api_key == "custom-key"
            assert service.default_model == "gemini-flash"

    def test_init_missing_key_raises(self) -> None:
        """Deve levantar erro se API key nao fornecida."""
        with (
            patch.dict("os.environ", {"OPENROUTER_API_KEY": ""}),
            pytest.raises(ValueError, match="OPENROUTER_API_KEY is required"),
        ):
            LLMService(api_key=None)

    def test_listar_modelos(self) -> None:
        """Deve listar modelo disponivel (apenas gemini-flash)."""
        with patch("services.llm_service.OpenRouter") as mock_openrouter:
            mock_openrouter.return_value = MagicMock()
            service = LLMService()
            modelos = service.listar_modelos()

            assert "gemini-flash" in modelos
            assert len(modelos) == 1

    def test_model_id_is_gemini(self) -> None:
        """Deve usar google/gemini-2.5-flash como unico modelo."""
        assert LLMService.MODEL_ID == "google/gemini-2.5-flash"

    @pytest.mark.asyncio
    async def test_verificar_contexto_small(self) -> None:
        """Deve verificar contexto pequeno."""
        with patch("services.llm_service.OpenRouter") as mock_openrouter:
            mock_openrouter.return_value = MagicMock()
            service = LLMService()

            contexto = "Texto pequeno de teste"
            result = await service.verificar_contexto(contexto)

            assert result["chars"] == len(contexto)
            assert result["cabe_no_modelo"] is True
            assert result["modelo_recomendado"] == "gemini-flash"

    @pytest.mark.asyncio
    async def test_verificar_contexto_large(self) -> None:
        """Deve recomendar gemini-flash para contexto grande."""
        with patch("services.llm_service.OpenRouter") as mock_openrouter:
            mock_openrouter.return_value = MagicMock()
            service = LLMService()

            contexto = "x" * 150000  # 150k chars
            result = await service.verificar_contexto(contexto)

            assert result["chars"] == 150000
            assert result["cabe_no_modelo"] is True
            assert result["modelo_recomendado"] == "gemini-flash"

    @pytest.mark.asyncio
    async def test_query(self) -> None:
        """Deve fazer query ao LLM."""
        with patch("services.llm_service.OpenRouter") as mock_openrouter:
            mock_client = MagicMock()
            mock_openrouter.return_value = mock_client

            # Setup mock response
            mock_response = MagicMock()
            mock_choice = MagicMock()
            mock_choice.message.content = "Resposta do LLM"
            mock_response.choices = [mock_choice]
            mock_response.usage = MagicMock(prompt_tokens=50, completion_tokens=20, total_tokens=70)
            mock_client.chat.send.return_value = mock_response

            service = LLMService()
            result = await service.query(
                pergunta="Qual o valor da causa?",
                contexto="Processo X com valor de R$ 50.000,00",
            )

            assert isinstance(result, LLMResponse)
            assert result.text == "Resposta do LLM"
            assert result.tokens_prompt == 50
            assert result.tokens_completion == 20


class TestGetLLMService:
    """Testes da factory function."""

    def test_get_llm_service_default(self) -> None:
        """Deve criar servico com modelo padrao."""
        with patch("services.llm_service.OpenRouter") as mock_openrouter:
            mock_openrouter.return_value = MagicMock()
            import services.llm_service as llm_mod

            llm_mod._instance = None  # Reset singleton
            service = get_llm_service()

            assert service.default_model == "gemini-flash"
            llm_mod._instance = None  # Cleanup
