"""User model for Mantimon TCG.

This module defines the User model for player accounts with OAuth support
and premium subscription tracking.

Example:
    user = User(
        email="player@example.com",
        display_name="Player1",
        oauth_provider="google",
        oauth_id="123456789"
    )
"""

from datetime import datetime
from typing import TYPE_CHECKING

from sqlalchemy import Boolean, DateTime, Index, String
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.db.base import Base

if TYPE_CHECKING:
    from app.db.models.campaign import CampaignProgress
    from app.db.models.collection import Collection
    from app.db.models.deck import Deck
    from app.db.models.oauth_account import OAuthLinkedAccount


class User(Base):
    """User account model with OAuth and premium support.

    Attributes:
        id: Unique identifier (UUID).
        email: User's email address (unique).
        display_name: Public display name.
        avatar_url: URL to user's avatar image.
        oauth_provider: OAuth provider name ('google', 'discord').
        oauth_id: Unique ID from the OAuth provider.
        is_premium: Whether user has active premium subscription.
        premium_until: When premium subscription expires.
        created_at: Account creation timestamp.
        last_login: Last login timestamp.

    Relationships:
        decks: User's deck configurations.
        collection: User's card collection.
        campaign_progress: User's campaign state.
        linked_accounts: Additional linked OAuth providers.
    """

    __tablename__ = "users"

    # Basic info
    email: Mapped[str] = mapped_column(
        String(255),
        unique=True,
        nullable=False,
        index=True,
        doc="User's email address",
    )
    display_name: Mapped[str] = mapped_column(
        String(50),
        nullable=False,
        doc="Public display name",
    )
    avatar_url: Mapped[str | None] = mapped_column(
        String(500),
        nullable=True,
        doc="URL to avatar image",
    )

    # OAuth
    oauth_provider: Mapped[str] = mapped_column(
        String(20),
        nullable=False,
        doc="OAuth provider name (google, discord)",
    )
    oauth_id: Mapped[str] = mapped_column(
        String(255),
        nullable=False,
        doc="Unique ID from OAuth provider",
    )

    # Premium subscription
    is_premium: Mapped[bool] = mapped_column(
        Boolean,
        default=False,
        nullable=False,
        doc="Whether user has active premium",
    )
    premium_until: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True),
        nullable=True,
        doc="Premium subscription expiration",
    )

    # Activity tracking
    last_login: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True),
        nullable=True,
        doc="Last login timestamp",
    )

    # Relationships
    decks: Mapped[list["Deck"]] = relationship(
        "Deck",
        back_populates="user",
        cascade="all, delete-orphan",
        lazy="selectin",
    )
    collection: Mapped[list["Collection"]] = relationship(
        "Collection",
        back_populates="user",
        cascade="all, delete-orphan",
        lazy="selectin",
    )
    campaign_progress: Mapped["CampaignProgress | None"] = relationship(
        "CampaignProgress",
        back_populates="user",
        cascade="all, delete-orphan",
        uselist=False,
        lazy="selectin",
    )
    linked_accounts: Mapped[list["OAuthLinkedAccount"]] = relationship(
        "OAuthLinkedAccount",
        back_populates="user",
        cascade="all, delete-orphan",
        lazy="selectin",
    )

    # Indexes
    __table_args__ = (Index("ix_users_oauth", "oauth_provider", "oauth_id", unique=True),)

    @property
    def has_active_premium(self) -> bool:
        """Check if premium subscription is currently active.

        Returns:
            True if user has premium and it hasn't expired.
        """
        if not self.is_premium:
            return False
        if self.premium_until is None:
            return False
        return datetime.now(self.premium_until.tzinfo) < self.premium_until

    @property
    def max_decks(self) -> int:
        """Get maximum number of decks user can have.

        Returns:
            5 for free users, unlimited (999) for premium.
        """
        return 999 if self.has_active_premium else 5

    def __repr__(self) -> str:
        return f"<User(id={self.id!r}, email={self.email!r})>"
