"""Tests for authentication module."""

import pytest

from crustdata_mcp.auth import CrustdataTokenVerifier, PassthroughTokenVerifier


class TestCrustdataTokenVerifier:
    """Tests for CrustdataTokenVerifier class."""

    @pytest.mark.asyncio
    async def test_valid_token(self):
        """Test that a valid token returns an AccessToken."""
        verifier = CrustdataTokenVerifier("test-secret-token")
        result = await verifier.verify_token("test-secret-token")

        assert result is not None
        assert result.token == "test-secret-token"
        assert result.client_id == "mcp-client"
        assert result.scopes == ["read", "write"]
        assert result.expires_at is None

    @pytest.mark.asyncio
    async def test_invalid_token(self):
        """Test that an invalid token returns None."""
        verifier = CrustdataTokenVerifier("test-secret-token")
        result = await verifier.verify_token("wrong-token")

        assert result is None

    @pytest.mark.asyncio
    async def test_empty_token(self):
        """Test that an empty token returns None."""
        verifier = CrustdataTokenVerifier("test-secret-token")
        result = await verifier.verify_token("")

        assert result is None

    @pytest.mark.asyncio
    async def test_token_comparison_is_exact(self):
        """Test that token comparison is exact (no partial matching)."""
        verifier = CrustdataTokenVerifier("test-token")

        # Prefix shouldn't match
        assert await verifier.verify_token("test-token-extra") is None
        # Suffix shouldn't match
        assert await verifier.verify_token("prefix-test-token") is None
        # Case sensitive
        assert await verifier.verify_token("TEST-TOKEN") is None
        # Whitespace matters
        assert await verifier.verify_token(" test-token") is None
        assert await verifier.verify_token("test-token ") is None


class TestPassthroughTokenVerifier:
    """Tests for PassthroughTokenVerifier class (per-request HTTP auth)."""

    @pytest.mark.asyncio
    async def test_accepts_any_valid_token(self):
        """Test that any non-empty, valid-length token is accepted."""
        verifier = PassthroughTokenVerifier()
        result = await verifier.verify_token("any-valid-token-12345")

        assert result is not None
        assert result.token == "any-valid-token-12345"
        assert result.client_id == "crustdata-api-client"
        assert result.scopes == ["read", "write"]
        assert result.expires_at is None

    @pytest.mark.asyncio
    async def test_accepts_different_tokens(self):
        """Test that the verifier accepts different valid tokens."""
        verifier = PassthroughTokenVerifier()

        token1 = await verifier.verify_token("first-token-abc123")
        token2 = await verifier.verify_token("second-token-xyz789")

        assert token1 is not None
        assert token2 is not None
        assert token1.token == "first-token-abc123"
        assert token2.token == "second-token-xyz789"

    @pytest.mark.asyncio
    async def test_rejects_empty_token(self):
        """Test that empty token is rejected."""
        verifier = PassthroughTokenVerifier()

        assert await verifier.verify_token("") is None

    @pytest.mark.asyncio
    async def test_rejects_whitespace_only_token(self):
        """Test that whitespace-only token is rejected."""
        verifier = PassthroughTokenVerifier()

        assert await verifier.verify_token("   ") is None
        assert await verifier.verify_token("\t\n") is None

    @pytest.mark.asyncio
    async def test_rejects_short_token(self):
        """Test that very short tokens are rejected (min length validation)."""
        verifier = PassthroughTokenVerifier()

        # Tokens shorter than MIN_TOKEN_LENGTH should be rejected
        assert await verifier.verify_token("abc") is None
        assert await verifier.verify_token("short") is None
        assert await verifier.verify_token("123456789") is None  # 9 chars

    @pytest.mark.asyncio
    async def test_accepts_minimum_length_token(self):
        """Test that tokens at minimum length are accepted."""
        verifier = PassthroughTokenVerifier()

        # MIN_TOKEN_LENGTH is 10
        result = await verifier.verify_token("1234567890")

        assert result is not None
        assert result.token == "1234567890"

    @pytest.mark.asyncio
    async def test_stores_original_token(self):
        """Test that the original token is stored and retrievable."""
        verifier = PassthroughTokenVerifier()
        original_token = "my-crustdata-api-token-secret"

        result = await verifier.verify_token(original_token)

        # The token field should contain the exact original token
        # This is how tools retrieve the token for API calls
        assert result is not None
        assert result.token == original_token
