"""
Authentication session model for storing active tokens and sessions.
"""

from __future__ import annotations
from datetime import datetime, timezone
from typing import Optional

from sqlalchemy import String, DateTime, Boolean, Text, ForeignKey, func
from sqlalchemy.orm import Mapped, mapped_column

from src.apps.base.models.base import Base


class AuthSession(Base):
    """
    Model for storing user authentication sessions and tokens.
    
    This table tracks active user sessions, refresh tokens, and provides
    the ability to revoke tokens for logout functionality.
    """
    
    __tablename__ = "auth_sessions"
    
    id: Mapped[int] = mapped_column(primary_key=True, index=True)
    
    # User relationship - temporarily commented out to avoid circular import issues
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), nullable=False, index=True)
    # TODO: Fix relationship configuration for distributed models
    # user: Mapped["User"] = relationship("User", back_populates="auth_sessions")
    
    # Token information
    access_token: Mapped[str] = mapped_column(Text, unique=True, index=True, nullable=False, doc="Access token for the session")
    refresh_token: Mapped[Optional[str]] = mapped_column(Text, unique=True, index=True, nullable=True, doc="Refresh token for the session")
    
    # Session information
    device_info: Mapped[Optional[str]] = mapped_column(Text, nullable=True, doc="Device/browser information")
    ip_address: Mapped[Optional[str]] = mapped_column(String(45), nullable=True, doc="IP address of the session")
    user_agent: Mapped[Optional[str]] = mapped_column(Text, nullable=True, doc="User agent string")
    
    # Token expiration times
    access_token_expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
    refresh_token_expires_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
    
    # Session status
    is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False, index=True)
    is_revoked: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False, index=True)
    
    # Timestamps
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=False)
    updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
    revoked_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
    last_activity_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=True)
    
    def __repr__(self) -> str:
        return f"<AuthSession(id={self.id}, user_id={self.user_id}, is_active={self.is_active})>"
    
    def revoke(self) -> None:
        """Revoke this session (logout)."""
        self.is_active = False
        self.is_revoked = True
        self.revoked_at = datetime.now(timezone.utc)
    
    def is_expired(self) -> bool:
        """Check if the access token is expired."""
        return self.access_token_expires_at < datetime.now(timezone.utc)
    
    def is_refresh_token_expired(self) -> bool:
        """Check if the refresh token is expired."""
        if not self.refresh_token_expires_at:
            return True
        return self.refresh_token_expires_at < datetime.now(timezone.utc)
    
    def update_activity(self) -> None:
        """Update last activity timestamp."""
        self.last_activity_at = datetime.now(timezone.utc)