from pydantic import BaseModel, EmailStr, Field, field_validator, ConfigDict
from typing import Optional, List
from datetime import datetime
from enum import Enum


class UserRole(str, Enum):
    ANONYMOUS = "ANONYMOUS"
    REGISTERED = "REGISTERED"
    DATA_MANAGER = "DATA_MANAGER"
    ADMINISTRATOR = "ADMINISTRATOR"


class UserStatus(str, Enum):
    ACTIVE = "ACTIVE"
    INACTIVE = "INACTIVE"
    SUSPENDED = "SUSPENDED"


class ActivityType(str, Enum):
    VIEW = "VIEW"
    SEARCH = "SEARCH"
    FAVORITE = "FAVORITE"


# User schemas
class UserBase(BaseModel):
    email: EmailStr
    first_name: Optional[str] = None
    last_name: Optional[str] = None
    role: UserRole = UserRole.REGISTERED
    status: UserStatus = UserStatus.ACTIVE
    profile_picture_url: Optional[str] = None
    preferences: Optional[dict] = None


class UserCreate(UserBase):
    password: str
    
    @field_validator("password")
    @classmethod
    def validate_password(cls, v: str) -> str:
        if len(v) < 8:
            raise ValueError("Password must be at least 8 characters long")
        if not any(c.isupper() for c in v):
            raise ValueError("Password must contain at least 1 uppercase letter")
        if not any(c.islower() for c in v):
            raise ValueError("Password must contain at least 1 lowercase letter")
        if not any(c.isdigit() for c in v):
            raise ValueError("Password must contain at least 1 number")
        return v
    
    @field_validator("email")
    @classmethod
    def validate_email(cls, v: str) -> str:
        if not v or "@" not in v:
            raise ValueError("Email must be a valid RFC 5322 compliant address")
        return v.lower()


class UserUpdate(BaseModel):
    email: Optional[EmailStr] = None
    first_name: Optional[str] = None
    last_name: Optional[str] = None
    role: Optional[UserRole] = None
    status: Optional[UserStatus] = None
    profile_picture_url: Optional[str] = None
    preferences: Optional[dict] = None
    password: Optional[str] = None
    
    @field_validator("password")
    @classmethod
    def validate_password(cls, v: Optional[str]) -> Optional[str]:
        if v is None:
            return v
        if len(v) < 8:
            raise ValueError("Password must be at least 8 characters long")
        if not any(c.isupper() for c in v):
            raise ValueError("Password must contain at least 1 uppercase letter")
        if not any(c.islower() for c in v):
            raise ValueError("Password must contain at least 1 lowercase letter")
        if not any(c.isdigit() for c in v):
            raise ValueError("Password must contain at least 1 number")
        return v
    
    @field_validator("email")
    @classmethod
    def validate_email(cls, v: Optional[str]) -> Optional[str]:
        if v is None:
            return v
        if not v or "@" not in v:
            raise ValueError("Email must be a valid RFC 5322 compliant address")
        return v.lower()


class UserResponse(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    
    id: str
    email: str
    first_name: Optional[str] = None
    last_name: Optional[str] = None
    role: str
    registration_date: datetime
    last_login_date: Optional[datetime] = None
    status: str
    profile_picture_url: Optional[str] = None
    preferences: Optional[dict] = None
    created_at: datetime
    updated_at: datetime


# UserActivity schemas
class UseractivityBase(BaseModel):
    user_id: str
    stock_id: str
    activity_type: ActivityType
    session_id: Optional[str] = None


class UseractivityCreate(UseractivityBase):
    timestamp: Optional[datetime] = None
    
    @field_validator("activity_type")
    @classmethod
    def validate_activity_type(cls, v: ActivityType) -> ActivityType:
        if v not in [ActivityType.VIEW, ActivityType.SEARCH, ActivityType.FAVORITE]:
            raise ValueError("Activity type must be one of: VIEW, SEARCH, FAVORITE")
        return v


class UseractivityUpdate(BaseModel):
    user_id: Optional[str] = None
    stock_id: Optional[str] = None
    activity_type: Optional[ActivityType] = None
    timestamp: Optional[datetime] = None
    session_id: Optional[str] = None


class UseractivityResponse(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    
    id: str
    user_id: str
    stock_id: str
    activity_type: str
    timestamp: datetime
    session_id: Optional[str] = None
    created_at: datetime
    updated_at: datetime


# Login/Register schemas
class UserLogin(BaseModel):
    email: EmailStr
    password: str


class UserRegister(UserCreate):
    pass


class LoginResponse(BaseModel):
    access_token: str
    token_type: str = "bearer"
    user: UserResponse


# User activities with stock details
class StockBasicInfo(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    
    ticker_symbol: str
    company_name: str
    current_price: Optional[float] = None


class UseractivityWithStock(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    
    id: str
    user_id: str
    stock_id: str
    activity_type: str
    timestamp: datetime
    session_id: Optional[str] = None
    stock: StockBasicInfo
    created_at: datetime
    updated_at: datetime