"""Tests for authentication handlers."""

import base64

import pytest

from concentriq.auth import ApiKeyAuth, BasicAuth, JWTAuth, SessionAuth


class TestBasicAuth:
    """Tests for BasicAuth handler."""

    def test_creates_with_username_and_password(self):
        """BasicAuth should accept username and password."""
        auth = BasicAuth(username="testuser", password="testpass")
        assert auth.username == "testuser"
        assert auth.password == "testpass"

    def test_generates_auth_header(self):
        """BasicAuth should generate proper Authorization header."""
        auth = BasicAuth(username="testuser", password="testpass")
        headers = auth.get_headers()

        # Decode the expected value
        credentials = base64.b64encode(b"testuser:testpass").decode("ascii")
        expected = f"Basic {credentials}"

        assert "Authorization" in headers
        assert headers["Authorization"] == expected

    def test_empty_username_raises_error(self):
        """BasicAuth should raise ValueError for empty username."""
        with pytest.raises(ValueError, match="Username cannot be empty"):
            BasicAuth(username="", password="testpass")

    def test_empty_password_raises_error(self):
        """BasicAuth should raise ValueError for empty password."""
        with pytest.raises(ValueError, match="Password cannot be empty"):
            BasicAuth(username="testuser", password="")


class TestApiKeyAuth:
    """Tests for ApiKeyAuth handler."""

    def test_creates_with_api_key(self):
        """ApiKeyAuth should accept an API key."""
        auth = ApiKeyAuth(api_key="test-key-123")
        assert auth.api_key == "test-key-123"

    def test_generates_api_key_header(self):
        """ApiKeyAuth should generate proper concentriq-api-key header."""
        auth = ApiKeyAuth(api_key="test-key-123")
        headers = auth.get_headers()

        assert "concentriq-api-key" in headers
        assert headers["concentriq-api-key"] == "test-key-123"

    def test_empty_api_key_raises_error(self):
        """ApiKeyAuth should raise ValueError for empty API key."""
        with pytest.raises(ValueError, match="API key cannot be empty"):
            ApiKeyAuth(api_key="")


class TestJWTAuth:
    """Tests for JWTAuth handler."""

    def test_creates_with_token(self):
        """JWTAuth should accept a JWT token."""
        auth = JWTAuth(token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.test")
        assert auth.token == "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.test"

    def test_generates_bearer_token_header(self):
        """JWTAuth should generate proper Authorization Bearer header."""
        token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.test"
        auth = JWTAuth(token=token)
        headers = auth.get_headers()

        assert "Authorization" in headers
        assert headers["Authorization"] == f"Bearer {token}"

    def test_empty_token_raises_error(self):
        """JWTAuth should raise ValueError for empty token."""
        with pytest.raises(ValueError, match="Token cannot be empty"):
            JWTAuth(token="")


class TestSessionAuth:
    """Tests for SessionAuth handler."""

    def test_creates_with_session_cookie(self):
        """SessionAuth should accept a session cookie value."""
        auth = SessionAuth(session_cookie="s%3Atest-session-id.signature")
        assert auth.session_cookie == "s%3Atest-session-id.signature"

    def test_generates_cookie_header(self):
        """SessionAuth should generate proper Cookie header."""
        cookie_value = "s%3Atest-session-id.signature"
        auth = SessionAuth(session_cookie=cookie_value)
        headers = auth.get_headers()

        assert "Cookie" in headers
        assert headers["Cookie"] == f"connect.sid={cookie_value}"

    def test_empty_session_cookie_raises_error(self):
        """SessionAuth should raise ValueError for empty session cookie."""
        with pytest.raises(ValueError, match="Session cookie cannot be empty"):
            SessionAuth(session_cookie="")

    def test_creates_with_custom_cookie_name(self):
        """SessionAuth should accept custom cookie name."""
        auth = SessionAuth(
            session_cookie="test-value",
            cookie_name="custom-session"
        )
        headers = auth.get_headers()

        assert headers["Cookie"] == "custom-session=test-value"

    def test_default_cookie_name_is_connect_sid(self):
        """SessionAuth should default to connect.sid cookie name."""
        auth = SessionAuth(session_cookie="test-value")
        assert auth.cookie_name == "connect.sid"
