"""
SQLAlchemy ORM models for user data features.

Includes sessions, decks, replays, cards, groups, and networks.
"""
from sqlalchemy import (
    Column, Integer, String, BigInteger, Boolean, DateTime, Text,
    ForeignKey, Index, UniqueConstraint, Float, JSON
)
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from app.core.database import Base


class UserSession(Base):
    """User authentication session."""
    __tablename__ = "user_sessions"
    
    id = Column(BigInteger, primary_key=True)
    user_id = Column(Integer, ForeignKey("mtgonline_users.id", ondelete="CASCADE"), nullable=False, index=True)
    session_token_hash = Column(String(255), unique=True, nullable=False, index=True)
    ip_address = Column(String(45), nullable=True)
    user_agent = Column(Text, nullable=True)
    created_at = Column(DateTime, server_default=func.now())
    expires_at = Column(DateTime, nullable=False)
    is_active = Column(Boolean, default=True)
    
    user = relationship("User", backref="sessions")
    
    def __repr__(self) -> str:
        return f"<UserSession user={self.user_id} expires={self.expires_at}>"


class DeckVersion(Base):
    """Deck version history."""
    __tablename__ = "deck_versions"
    
    id = Column(BigInteger, primary_key=True)
    deck_id = Column(Integer, ForeignKey("mtgonline_decklist_files.id", ondelete="CASCADE"), nullable=False, index=True)
    version_number = Column(Integer, nullable=False)
    content = Column(Text, nullable=False)
    status = Column(String(20), server_default="DRAFT")
    comment = Column(Text, nullable=True)
    created_at = Column(DateTime, server_default=func.now())
    
    deck = relationship("DecklistFile", backref="versions")
    
    def __repr__(self) -> str:
        return f"<DeckVersion deck={self.deck_id} v={self.version_number}>"


class GameReplay(Base):
    """Game replay recording."""
    __tablename__ = "game_replays"
    
    id = Column(BigInteger, primary_key=True)
    game_uuid = Column(String(36), unique=True, nullable=False)
    room_id = Column(Integer, ForeignKey("mtgonline_rooms.id"), nullable=True, index=True)
    game_type = Column(String(50), nullable=True)
    format = Column(String(50), nullable=True)
    duration_seconds = Column(Integer, nullable=True)
    start_time = Column(DateTime, nullable=False)
    end_time = Column(DateTime, nullable=True)
    status = Column(String(20), server_default="IN_PROGRESS")
    replay_data = Column(JSON, nullable=True)
    created_at = Column(DateTime, server_default=func.now())
    updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
    
    players = relationship("ReplayPlayer", back_populates="replay", cascade="all, delete-orphan")
    outcomes = relationship("GameOutcome", back_populates="replay", cascade="all, delete-orphan")
    
    def __repr__(self) -> str:
        return f"<GameReplay {self.game_uuid} status={self.status}>"


class ReplayPlayer(Base):
    """Player in a game replay."""
    __tablename__ = "replay_players"
    
    id = Column(BigInteger, primary_key=True)
    replay_id = Column(BigInteger, ForeignKey("game_replays.id", ondelete="CASCADE"), nullable=False, index=True)
    user_id = Column(Integer, ForeignKey("mtgonline_users.id"), nullable=False, index=True)
    position = Column(Integer, nullable=True)
    deck_id = Column(Integer, ForeignKey("mtgonline_decklist_files.id"), nullable=True)
    won = Column(Boolean, nullable=True)
    lost = Column(Boolean, nullable=True)
    concession = Column(Boolean, default=False)
    turn_one = Column(Boolean, default=False)
    created_at = Column(DateTime, server_default=func.now())
    
    replay = relationship("GameReplay", back_populates="players")
    user = relationship("User")
    deck = relationship("DecklistFile")
    
    def __repr__(self) -> str:
        return f"<ReplayPlayer replay={self.replay_id} user={self.user_id}>"


class GameOutcome(Base):
    """Game outcome record."""
    __tablename__ = "game_outcomes"
    
    id = Column(BigInteger, primary_key=True)
    user_id = Column(Integer, ForeignKey("mtgonline_users.id"), nullable=False, index=True)
    game_uuid = Column(String(36), ForeignKey("game_replays.game_uuid"), nullable=False, index=True)
    outcome = Column(String(20), nullable=False, index=True)
    opponent_id = Column(Integer, ForeignKey("mtgonline_users.id"), nullable=True)
    format = Column(String(50), nullable=True)
    rating_before = Column(Integer, nullable=True)
    rating_after = Column(Integer, nullable=True)
    rating_change = Column(Integer, nullable=True)
    created_at = Column(DateTime, server_default=func.now())
    
    replay = relationship("GameReplay", back_populates="outcomes")
    user = relationship("User", foreign_keys=[user_id])
    opponent = relationship("User", foreign_keys=[opponent_id])
    
    def __repr__(self) -> str:
        return f"<GameOutcome user={self.user_id} {self.outcome}>"


class UserStatistics(Base):
    """User game statistics summary."""
    __tablename__ = "user_statistics"
    
    user_id = Column(Integer, ForeignKey("mtgonline_users.id"), primary_key=True)
    total_games = Column(Integer, default=0)
    total_wins = Column(Integer, default=0)
    total_losses = Column(Integer, default=0)
    total_concessions = Column(Integer, default=0)
    win_rate = Column(Float, default=0.0)
    current_streak = Column(Integer, default=0)
    best_streak = Column(Integer, default=0)
    average_rating = Column(Float, default=0.0)
    last_game_date = Column(DateTime, nullable=True)
    updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
    
    user = relationship("User")
    
    def __repr__(self) -> str:
        return f"<UserStatistics user={self.user_id} wins={self.total_wins} losses={self.total_losses}>"


class UserCardCollection(Base):
    """User card collection."""
    __tablename__ = "user_card_collection"
    
    id = Column(BigInteger, primary_key=True)
    user_id = Column(Integer, ForeignKey("mtgonline_users.id", ondelete="CASCADE"), nullable=False, index=True)
    card_id = Column(Integer, nullable=False, index=True)
    quantity = Column(Integer, default=1)
    condition = Column(String(20), server_default="NEAR_MINT")
    language = Column(String(5), server_default="EN")
    is_foil = Column(Boolean, default=False)
    is_alt_art = Column(Boolean, default=False)
    acquired_date = Column(DateTime, server_default=func.now())
    acquisition_method = Column(String(50), nullable=True)
    notes = Column(Text, nullable=True)
    created_at = Column(DateTime, server_default=func.now())
    updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
    
    __table_args__ = (
        UniqueConstraint('user_id', 'card_id', 'is_foil', 'is_alt_art', name='uq_collection_unique'),
        Index('idx_collection_user_card', 'user_id', 'card_id'),
    )
    
    user = relationship("User", backref="card_collection")
    
    def __repr__(self) -> str:
        return f"<UserCard user={self.user_id} card={self.card_id} qty={self.quantity}>"


class CardWishlist(Base):
    """User card wishlist."""
    __tablename__ = "card_wishlist"
    
    id = Column(BigInteger, primary_key=True)
    user_id = Column(Integer, ForeignKey("mtgonline_users.id", ondelete="CASCADE"), nullable=False)
    card_id = Column(Integer, nullable=False)
    max_price = Column(Float, nullable=True)
    notes = Column(Text, nullable=True)
    created_at = Column(DateTime, server_default=func.now())
    
    __table_args__ = (
        UniqueConstraint('user_id', 'card_id', name='uq_wishlist_user_card'),
    )
    
    user = relationship("User", backref="wishlist")
    
    def __repr__(self) -> str:
        return f"<CardWishlist user={self.user_id} card={self.card_id}>"


class UserGroup(Base):
    """User group."""
    __tablename__ = "user_groups"
    
    id = Column(BigInteger, primary_key=True)
    name = Column(String(100), nullable=False)
    description = Column(Text, nullable=True)
    owner_id = Column(Integer, ForeignKey("mtgonline_users.id"), nullable=False, index=True)
    is_public = Column(Boolean, default=True)
    max_members = Column(Integer, default=50)
    created_at = Column(DateTime, server_default=func.now())
    updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
    
    owner = relationship("User", foreign_keys=[owner_id])
    members = relationship("GroupMember", back_populates="group", cascade="all, delete-orphan")
    messages = relationship("GroupChatMessage", back_populates="group", cascade="all, delete-orphan")
    
    def __repr__(self) -> str:
        return f"<UserGroup {self.name} owner={self.owner_id}>"


class GroupMember(Base):
    """Group member."""
    __tablename__ = "group_members"
    
    id = Column(BigInteger, primary_key=True)
    group_id = Column(BigInteger, ForeignKey("user_groups.id", ondelete="CASCADE"), nullable=False, index=True)
    user_id = Column(Integer, ForeignKey("mtgonline_users.id"), nullable=False, index=True)
    role = Column(String(20), server_default="MEMBER")
    joined_at = Column(DateTime, server_default=func.now())
    
    group = relationship("UserGroup", back_populates="members")
    user = relationship("User")
    
    __table_args__ = (
        UniqueConstraint('group_id', 'user_id', name='uq_group_member'),
    )
    
    def __repr__(self) -> str:
        return f"<GroupMember group={self.group_id} user={self.user_id} role={self.role}>"


class GroupChatMessage(Base):
    """Group chat message."""
    __tablename__ = "group_chat_messages"
    
    id = Column(BigInteger, primary_key=True)
    group_id = Column(BigInteger, ForeignKey("user_groups.id", ondelete="CASCADE"), nullable=False, index=True)
    sender_id = Column(Integer, ForeignKey("mtgonline_users.id"), nullable=False, index=True)
    message = Column(Text, nullable=False)
    created_at = Column(DateTime, server_default=func.now(), index=True)
    
    group = relationship("UserGroup", back_populates="messages")
    sender = relationship("User", foreign_keys=[sender_id])
    
    def __repr__(self) -> str:
        return f"<GroupChatMessage group={self.group_id} sender={self.sender_id}>"


class UserNetwork(Base):
    """User network (extended social connection)."""
    __tablename__ = "user_networks"
    
    id = Column(BigInteger, primary_key=True)
    name = Column(String(100), nullable=False)
    description = Column(Text, nullable=True)
    creator_id = Column(Integer, ForeignKey("mtgonline_users.id"), nullable=False)
    is_public = Column(Boolean, default=True)
    created_at = Column(DateTime, server_default=func.now())
    
    creator = relationship("User", foreign_keys=[creator_id])
    members = relationship("NetworkMember", back_populates="network", cascade="all, delete-orphan")
    
    def __repr__(self) -> str:
        return f"<UserNetwork {self.name} creator={self.creator_id}>"


class NetworkMember(Base):
    """Network member."""
    __tablename__ = "network_members"
    
    id = Column(BigInteger, primary_key=True)
    network_id = Column(BigInteger, ForeignKey("user_networks.id", ondelete="CASCADE"), nullable=False, index=True)
    user_id = Column(Integer, ForeignKey("mtgonline_users.id"), nullable=False, index=True)
    role = Column(String(20), server_default="MEMBER")
    joined_at = Column(DateTime, server_default=func.now())
    
    network = relationship("UserNetwork", back_populates="members")
    user = relationship("User")
    
    __table_args__ = (
        UniqueConstraint('network_id', 'user_id', name='uq_network_member'),
    )
    
    def __repr__(self) -> str:
        return f"<NetworkMember network={self.network_id} user={self.user_id} role={self.role}>"


class UserPreference(Base):
    """User preferences and settings."""
    __tablename__ = "user_preferences"
    
    user_id = Column(Integer, ForeignKey("mtgonline_users.id"), primary_key=True)
    theme = Column(String(20), server_default="light")
    notifications_enabled = Column(Boolean, default=True)
    email_notifications = Column(Boolean, default=True)
    auto_save_decks = Column(Boolean, default=True)
    default_format = Column(String(50), server_default="standard")
    language = Column(String(5), server_default="EN")
    updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
    
    user = relationship("User")
    
    def __repr__(self) -> str:
        return f"<UserPreference user={self.user_id} theme={self.theme}>"


class UserActivityLog(Base):
    """User activity log."""
    __tablename__ = "user_activity_log"
    
    id = Column(BigInteger, primary_key=True)
    user_id = Column(Integer, ForeignKey("mtgonline_users.id"), nullable=False, index=True)
    activity_type = Column(String(50), nullable=False, index=True)
    activity_data = Column(JSON, nullable=True)
    ip_address = Column(String(45), nullable=True)
    created_at = Column(DateTime, server_default=func.now(), index=True)
    
    user = relationship("User", backref="activity_logs")
    
    def __repr__(self) -> str:
        return f"<UserActivity user={self.user_id} type={self.activity_type}>"
