"""OAuth linked account model for Mantimon TCG.

This module defines the OAuthLinkedAccount model for supporting multiple
OAuth providers per user (account linking).

A user can have multiple linked accounts (e.g., both Google and Discord),
allowing them to log in with either provider.

Example:
    # User links Discord to their existing Google account
    linked_account = OAuthLinkedAccount(
        user_id=user.id,
        provider="discord",
        oauth_id="123456789",
        email="player@example.com"
    )
"""

from datetime import datetime
from typing import TYPE_CHECKING

from sqlalchemy import DateTime, ForeignKey, Index, String, func
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.db.base import Base

if TYPE_CHECKING:
    from app.db.models.user import User


class OAuthLinkedAccount(Base):
    """Linked OAuth account for multi-provider authentication.

    Allows users to link multiple OAuth providers to a single account,
    enabling login via any linked provider.

    The User model still has oauth_provider/oauth_id for the "primary"
    provider (the one used to create the account). This table tracks
    additional linked providers.

    Attributes:
        id: Unique identifier (UUID).
        user_id: Foreign key to the user who owns this linked account.
        provider: OAuth provider name ('google', 'discord').
        oauth_id: Unique ID from the OAuth provider.
        email: Email address from this OAuth provider (may differ from user's primary email).
        display_name: Display name from this OAuth provider.
        avatar_url: Avatar URL from this OAuth provider.
        linked_at: When this account was linked.

    Relationships:
        user: The User who owns this linked account.
    """

    __tablename__ = "oauth_linked_accounts"

    # Foreign key to user
    user_id: Mapped[str] = mapped_column(
        UUID(as_uuid=False),
        ForeignKey("users.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
        doc="User who owns this linked account",
    )

    # OAuth provider info
    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",
    )

    # Additional info from provider
    email: Mapped[str | None] = mapped_column(
        String(255),
        nullable=True,
        doc="Email from this OAuth provider",
    )
    display_name: Mapped[str | None] = mapped_column(
        String(100),
        nullable=True,
        doc="Display name from this OAuth provider",
    )
    avatar_url: Mapped[str | None] = mapped_column(
        String(500),
        nullable=True,
        doc="Avatar URL from this OAuth provider",
    )

    # When linked
    linked_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        server_default=func.now(),
        nullable=False,
        doc="When this account was linked",
    )

    # Relationship back to user
    user: Mapped["User"] = relationship(
        "User",
        back_populates="linked_accounts",
    )

    # Indexes and constraints
    __table_args__ = (
        # Each OAuth provider+ID can only be linked to one user
        Index(
            "ix_oauth_linked_accounts_provider_oauth_id",
            "provider",
            "oauth_id",
            unique=True,
        ),
    )

    def __repr__(self) -> str:
        return f"<OAuthLinkedAccount(user_id={self.user_id!r}, provider={self.provider!r})>"
