"""
User Model
Supports multiple roles: Passenger, Driver, Admin, Sub-admin
"""
import enum
from datetime import datetime
from typing import Optional, List
from sqlalchemy import String, Boolean, Enum, Text, DateTime, Index
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.models.base import BaseModel


class UserRole(str, enum.Enum):
    """User role enumeration"""
    PASSENGER = "passenger"
    DRIVER = "driver"
    ADMIN = "admin"
    SUB_ADMIN = "sub_admin"


class User(BaseModel):
    """
    User model for authentication and profile management.
    Supports both passengers and drivers with role differentiation.
    """
    __tablename__ = "users"
    
    # Basic Info
    email: Mapped[Optional[str]] = mapped_column(
        String(255),
        unique=True,
        index=True,
        nullable=True
    )
    phone: Mapped[Optional[str]] = mapped_column(
        String(20),
        unique=True,
        index=True,
        nullable=True
    )
    password_hash: Mapped[Optional[str]] = mapped_column(
        String(255),
        nullable=True  # Nullable for social auth users
    )
    
    # Profile
    first_name: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
    last_name: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
    profile_picture: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    date_of_birth: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    gender: Mapped[Optional[str]] = mapped_column(String(20), nullable=True)
    
    # Role and Status
    role: Mapped[UserRole] = mapped_column(
        Enum(UserRole),
        default=UserRole.PASSENGER,
        nullable=False,
        index=True
    )
    is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
    is_verified: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    is_email_verified: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    is_phone_verified: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    is_blocked: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    blocked_reason: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    
    # OTP verification
    otp_code: Mapped[Optional[str]] = mapped_column(String(10), nullable=True)
    otp_expires_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    
    # Social OAuth
    google_id: Mapped[Optional[str]] = mapped_column(String(255), unique=True, nullable=True)
    facebook_id: Mapped[Optional[str]] = mapped_column(String(255), unique=True, nullable=True)
    apple_id: Mapped[Optional[str]] = mapped_column(String(255), unique=True, nullable=True)
    
    # Tokens
    refresh_token: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
    device_token: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)  # FCM token
    
    # Address (optional)
    address: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    city: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
    state: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
    country: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
    postal_code: Mapped[Optional[str]] = mapped_column(String(20), nullable=True)
    
    # Metadata
    last_login_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    login_count: Mapped[int] = mapped_column(default=0, nullable=False)
    
    # Relationships
    driver_profile: Mapped[Optional["Driver"]] = relationship(
        "Driver",
        back_populates="user",
        foreign_keys="Driver.user_id",
        uselist=False
    )
    wallet: Mapped[Optional["Wallet"]] = relationship(
        "Wallet",
        back_populates="user",
        uselist=False
    )
    notifications: Mapped[List["Notification"]] = relationship(
        "Notification",
        back_populates="user",
        lazy="dynamic"
    )
    
    # Indexes
    __table_args__ = (
        Index('idx_user_email_active', 'email', 'is_active'),
        Index('idx_user_phone_active', 'phone', 'is_active'),
        Index('idx_user_role_active', 'role', 'is_active'),
    )
    
    @property
    def full_name(self) -> str:
        """Get user's full name"""
        parts = [self.first_name, self.last_name]
        return " ".join(filter(None, parts)) or "User"
    
    @property
    def is_driver(self) -> bool:
        """Check if user is a driver"""
        return self.role == UserRole.DRIVER
    
    @property
    def is_admin(self) -> bool:
        """Check if user is admin or sub-admin"""
        return self.role in [UserRole.ADMIN, UserRole.SUB_ADMIN]


# Import for type hints (avoid circular imports)
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from app.models.driver import Driver
    from app.models.payment import Wallet
    from app.models.notification import Notification
