"""Testes para autenticacao JWT."""

from unittest.mock import patch

import pytest
from jose import JWTError

from auth import SupabaseJWTVerifier, TokenPayload, extract_token_from_header


class TestSupabaseJWTVerifier:
    """Testes da classe SupabaseJWTVerifier."""

    def test_init_with_env_vars(self) -> None:
        """Deve inicializar com variaveis de ambiente."""
        with patch.dict(
            "os.environ",
            {
                "SUPABASE_URL": "https://test.supabase.co",
                "SUPABASE_JWT_SECRET": "test-secret",
            },
        ):
            verifier = SupabaseJWTVerifier()

            assert verifier.supabase_url == "https://test.supabase.co"
            assert verifier.issuer == "https://test.supabase.co/auth/v1"

    def test_init_with_explicit_values(self) -> None:
        """Deve aceitar valores explicitos."""
        verifier = SupabaseJWTVerifier(
            supabase_url="https://custom.supabase.co",
            jwt_secret="custom-secret",
        )

        assert verifier.supabase_url == "https://custom.supabase.co"
        assert verifier.jwt_secret == "custom-secret"

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

    def test_init_missing_secret_raises(self) -> None:
        """Deve levantar erro se jwt_secret nao fornecida."""
        with (
            patch.dict("os.environ", {"SUPABASE_URL": "url", "SUPABASE_JWT_SECRET": ""}),
            pytest.raises(ValueError, match="SUPABASE_JWT_SECRET is required"),
        ):
            SupabaseJWTVerifier(supabase_url="url", jwt_secret=None)

    def test_verify_invalid_token_raises(self) -> None:
        """Deve levantar erro para token invalido."""
        verifier = SupabaseJWTVerifier(
            supabase_url="https://test.supabase.co",
            jwt_secret="test-secret",
        )

        with pytest.raises(JWTError):
            verifier.verify_token("invalid-token")


class TestTokenPayload:
    """Testes do modelo TokenPayload."""

    def test_create_payload(self) -> None:
        """Deve criar payload com campos obrigatorios."""
        payload = TokenPayload(sub="user-123")

        assert payload.sub == "user-123"
        assert payload.email is None

    def test_create_payload_full(self) -> None:
        """Deve criar payload com todos os campos."""
        payload = TokenPayload(
            sub="user-123",
            email="test@example.com",
            role="authenticated",
            aud="authenticated",
        )

        assert payload.sub == "user-123"
        assert payload.email == "test@example.com"
        assert payload.role == "authenticated"


class TestExtractTokenFromHeader:
    """Testes da funcao extract_token_from_header."""

    def test_extract_valid_token(self) -> None:
        """Deve extrair token valido."""
        token = extract_token_from_header("Bearer abc123")
        assert token == "abc123"

    def test_extract_none_header(self) -> None:
        """Deve retornar None para header None."""
        token = extract_token_from_header(None)
        assert token is None

    def test_extract_invalid_format(self) -> None:
        """Deve retornar None para formato invalido."""
        token = extract_token_from_header("InvalidFormat abc123")
        assert token is None

    def test_extract_empty_bearer(self) -> None:
        """Deve extrair token vazio se Bearer sem valor."""
        token = extract_token_from_header("Bearer ")
        assert token == ""
