"""Unit tests for User model properties.

Tests the computed properties on the User model that don't require
database access.
"""

from datetime import UTC, datetime
from unittest.mock import MagicMock
from uuid import uuid4

import pytest

from app.db.models.user import User


@pytest.fixture
def user():
    """Create a test user with minimal attributes.

    Returns a User model instance without database persistence.
    """
    user = User(
        email="test@example.com",
        display_name="Test User",
        avatar_url=None,
        oauth_provider="google",
        oauth_id="google-123",
        is_premium=False,
        premium_until=None,
    )
    user.id = uuid4()
    user.created_at = datetime.now(UTC)
    user.updated_at = datetime.now(UTC)
    user.decks = []
    user.linked_accounts = []
    return user


class TestHasStarterDeck:
    """Tests for the has_starter_deck computed property."""

    def test_returns_false_when_no_decks(self, user):
        """Test has_starter_deck is False when user has no decks.

        New users start with no decks, so has_starter_deck should be False.
        This is used by the frontend to redirect to starter selection.
        """
        user.decks = []
        assert user.has_starter_deck is False

    def test_returns_false_when_only_regular_decks(self, user):
        """Test has_starter_deck is False when user only has regular decks.

        Users can create custom decks without selecting a starter.
        has_starter_deck should only be True for actual starter decks.
        """
        regular_deck = MagicMock()
        regular_deck.is_starter = False
        user.decks = [regular_deck]
        assert user.has_starter_deck is False

    def test_returns_true_when_has_starter_deck(self, user):
        """Test has_starter_deck is True when user has selected a starter.

        After selecting a starter deck, the property should return True.
        This allows the frontend to skip the starter selection page.
        """
        starter_deck = MagicMock()
        starter_deck.is_starter = True
        user.decks = [starter_deck]
        assert user.has_starter_deck is True

    def test_returns_true_when_starter_among_multiple_decks(self, user):
        """Test has_starter_deck is True even with mixed deck types.

        Users can have both starter and custom decks. As long as one
        starter deck exists, the property should return True.
        """
        regular_deck = MagicMock()
        regular_deck.is_starter = False
        starter_deck = MagicMock()
        starter_deck.is_starter = True
        user.decks = [regular_deck, starter_deck]
        assert user.has_starter_deck is True


class TestMaxDecks:
    """Tests for the max_decks computed property."""

    def test_returns_5_for_free_users(self, user):
        """Test free users have 5 deck slots.

        Free users should be limited to 5 decks to encourage premium upgrades.
        """
        user.is_premium = False
        assert user.max_decks == 5

    def test_returns_999_for_premium_users(self, user):
        """Test premium users have unlimited deck slots.

        Premium users get 999 slots (effectively unlimited) as a benefit.
        """
        from datetime import timedelta

        user.is_premium = True
        user.premium_until = datetime.now(UTC) + timedelta(days=30)
        assert user.max_decks == 999

    def test_returns_5_for_expired_premium(self, user):
        """Test expired premium users revert to free limits.

        When premium expires, users should be treated as free users.
        """
        from datetime import timedelta

        user.is_premium = True
        user.premium_until = datetime.now(UTC) - timedelta(days=1)  # Expired
        assert user.max_decks == 5
