"""Tests for JWT token validation."""

import pytest

from conduit_auth.exceptions import AuthenticationError, TokenExpiredError
from conduit_auth.token import validate_token


class TestValidateToken:
    """Tests for validate_token()."""

    def test_valid_token(self, make_token, jwks_keys, auth_settings):
        token = make_token()
        user = validate_token(token, jwks_keys, auth_settings)

        assert user.tenant_id == "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
        assert user.user_id == "11111111-2222-3333-4444-555555555555"
        assert user.email == "user@example.com"
        assert user.display_name == "Test User"
        assert user.roles == []
        assert "tid" in user.raw_claims

    def test_valid_token_with_roles(self, make_token, jwks_keys, auth_settings):
        token = make_token(extra_claims={"roles": ["Admin", "Reader"]})
        user = validate_token(token, jwks_keys, auth_settings)

        assert user.roles == ["Admin", "Reader"]

    def test_expired_token(self, make_token, jwks_keys, auth_settings):
        token = make_token(expired=True)

        with pytest.raises(TokenExpiredError, match="expired"):
            validate_token(token, jwks_keys, auth_settings)

    def test_wrong_audience(self, make_token, jwks_keys, auth_settings):
        token = make_token(audience="wrong-audience")

        with pytest.raises(AuthenticationError, match="audience"):
            validate_token(token, jwks_keys, auth_settings)

    def test_invalid_issuer(self, make_token, jwks_keys, auth_settings):
        token = make_token(issuer="https://evil.example.com/v2.0")

        with pytest.raises(AuthenticationError, match="issuer"):
            validate_token(token, jwks_keys, auth_settings)

    def test_v1_issuer_accepted(self, make_token, jwks_keys, auth_settings):
        tid = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
        token = make_token(issuer=f"https://sts.windows.net/{tid}/")
        user = validate_token(token, jwks_keys, auth_settings)

        assert user.tenant_id == tid

    def test_multi_tenant_different_tenants(
        self, make_token, jwks_keys, auth_settings
    ):
        """Tokens from different tenants should all be accepted."""
        for tid in [
            "11111111-1111-1111-1111-111111111111",
            "22222222-2222-2222-2222-222222222222",
            "33333333-3333-3333-3333-333333333333",
        ]:
            token = make_token(tenant_id=tid)
            user = validate_token(token, jwks_keys, auth_settings)
            assert user.tenant_id == tid

    def test_unknown_kid(self, make_token, jwks_keys, auth_settings):
        token = make_token(use_kid="unknown-kid")

        with pytest.raises(AuthenticationError, match="not found"):
            validate_token(token, jwks_keys, auth_settings)

    def test_malformed_token(self, jwks_keys, auth_settings):
        with pytest.raises(AuthenticationError, match="Malformed"):
            validate_token("not-a-jwt", jwks_keys, auth_settings)

    def test_custom_audience_setting(
        self, make_token, jwks_keys, test_client_id
    ):
        custom_audience = "api://my-custom-audience"
        settings = type(
            "Settings",
            (),
            {
                "ENTRA_CLIENT_ID": test_client_id,
                "ENTRA_AUDIENCE": custom_audience,
            },
        )()
        token = make_token(audience=custom_audience)
        user = validate_token(token, jwks_keys, settings)

        assert user.email == "user@example.com"
