"""Testes para o cliente Supabase."""

from unittest.mock import MagicMock, patch

import pytest

from services.supabase_client import SupabaseClient, get_supabase_client


class TestSupabaseClient:
    """Testes da classe SupabaseClient."""

    def test_init_with_env_vars(self) -> None:
        """Deve inicializar com variaveis de ambiente."""
        with patch("services.supabase_client.create_client") as mock_create:
            mock_create.return_value = MagicMock()
            client = SupabaseClient()

            assert client.url == "https://test.supabase.co"
            assert client.service_key == "test-service-key"
            mock_create.assert_called_once()

    def test_init_with_explicit_values(self) -> None:
        """Deve aceitar valores explicitos."""
        with patch("services.supabase_client.create_client") as mock_create:
            mock_create.return_value = MagicMock()
            client = SupabaseClient(
                url="https://custom.supabase.co",
                service_key="custom-key",
                user_id="user-123",
            )

            assert client.url == "https://custom.supabase.co"
            assert client.service_key == "custom-key"
            assert client.user_id == "user-123"

    def test_init_missing_url_raises(self) -> None:
        """Deve levantar erro se URL nao fornecida."""
        with (
            patch.dict("os.environ", {"SUPABASE_URL": "", "SUPABASE_SERVICE_KEY": "key"}),
            pytest.raises(ValueError, match="SUPABASE_URL is required"),
        ):
            SupabaseClient(url=None, service_key="key")

    def test_init_missing_key_raises(self) -> None:
        """Deve levantar erro se service_key nao fornecida."""
        with (
            patch.dict("os.environ", {"SUPABASE_URL": "url", "SUPABASE_SERVICE_KEY": ""}),
            pytest.raises(ValueError, match="SUPABASE_SERVICE_KEY is required"),
        ):
            SupabaseClient(url="url", service_key=None)


class TestSupabaseClientMethods:
    """Testes dos metodos do SupabaseClient."""

    @pytest.fixture
    def client_with_mock(self) -> tuple[SupabaseClient, MagicMock]:
        """Cliente com Supabase mockado."""
        with patch("services.supabase_client.create_client") as mock_create:
            mock_supabase = MagicMock()
            mock_create.return_value = mock_supabase
            client = SupabaseClient()
            return client, mock_supabase

    @pytest.mark.asyncio
    async def test_buscar_processo(
        self, client_with_mock: tuple[SupabaseClient, MagicMock], sample_processo: dict
    ) -> None:
        """Deve buscar processo por numero."""
        client, mock_supabase = client_with_mock

        # Setup mock chain
        mock_table = MagicMock()
        mock_supabase.table.return_value = mock_table
        mock_table.select.return_value = mock_table
        mock_table.eq.return_value = mock_table
        mock_table.limit.return_value = mock_table
        mock_table.execute.return_value = MagicMock(data=[sample_processo])

        result = await client.buscar_processo("0000001-00.2024.8.26.0100")

        assert result == sample_processo
        mock_supabase.table.assert_called_with("processos")

    @pytest.mark.asyncio
    async def test_buscar_processo_not_found(
        self, client_with_mock: tuple[SupabaseClient, MagicMock]
    ) -> None:
        """Deve retornar None se processo nao encontrado."""
        client, mock_supabase = client_with_mock

        mock_table = MagicMock()
        mock_supabase.table.return_value = mock_table
        mock_table.select.return_value = mock_table
        mock_table.eq.return_value = mock_table
        mock_table.limit.return_value = mock_table
        mock_table.execute.return_value = MagicMock(data=None)

        result = await client.buscar_processo("0000000-00.0000.0.00.0000")

        assert result is None

    @pytest.mark.asyncio
    async def test_listar_documentos(
        self, client_with_mock: tuple[SupabaseClient, MagicMock], sample_documento: dict
    ) -> None:
        """Deve listar documentos de um processo."""
        client, mock_supabase = client_with_mock

        mock_table = MagicMock()
        mock_supabase.table.return_value = mock_table
        mock_table.select.return_value = mock_table
        mock_table.eq.return_value = mock_table
        mock_table.order.return_value = mock_table
        mock_table.limit.return_value = mock_table
        mock_table.execute.return_value = MagicMock(data=[sample_documento])

        result = await client.listar_documentos("0000001-00.2024.8.26.0100")

        assert len(result) == 1
        assert result[0]["id"] == "doc-uuid-123"


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

    def test_get_supabase_client(self) -> None:
        """Deve criar cliente via factory."""
        with patch("services.supabase_client.create_client") as mock_create:
            mock_create.return_value = MagicMock()
            client = get_supabase_client(user_id="user-123")

            assert isinstance(client, SupabaseClient)
            assert client.user_id == "user-123"
