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


class UserRegister(BaseModel):
    """User registration request."""
    username: str = Field(..., min_length=3, max_length=50)
    email: EmailStr
    password: str = Field(..., min_length=8)
    full_name: Optional[str] = Field(None, max_length=100)
    
    @field_validator('username')
    @classmethod
    def username_alphanumeric(cls, v):
        if not v.replace('_', '').replace('-', '').isalnum():
            raise ValueError('Username must be alphanumeric with optional hyphens/underscores')
        return v


class UserLogin(BaseModel):
    """User login request."""
    username: str
    password: str


class UserLoginWithMFA(BaseModel):
    """User login with MFA code."""
    username: str
    password: str
    mfa_code: Optional[str] = Field(None, min_length=6, max_length=8)
    
    @field_validator('mfa_code')
    @classmethod
    def validate_mfa_code(cls, v):
        if v is None:
            return v
        v = v.upper().strip()
        if len(v) == 6 and v.isdigit():
            return v
        elif len(v) == 8 and v.isalnum():
            return v
        else:
            raise ValueError('MFA code must be 6 digits or 8 alphanumeric characters')


class TokenResponse(BaseModel):
    """Token response."""
    access_token: str = ""
    refresh_token: str = ""
    token_type: str = "bearer"
    requires_mfa: bool = False
    message: Optional[str] = None
    next_step: Optional[str] = None


class RefreshTokenRequest(BaseModel):
    """Refresh token request."""
    refresh_token: str


class MFASetupResponse(BaseModel):
    """MFA setup response."""
    secret: str
    provisioning_uri: str
    qr_code: str  # Base64 encoded QR code
    backup_codes: List[str]


class MFAVerifyRequest(BaseModel):
    """MFA verification request - accepts TOTP or backup code."""
    code: str = Field(..., min_length=6, max_length=8)
    
    @field_validator('code')
    @classmethod
    def validate_code(cls, v):
        v = v.upper().strip()
        if len(v) == 6 and v.isdigit():
            return v  # Valid TOTP
        elif len(v) == 8 and v.isalnum():
            return v  # Valid backup code
        else:
            raise ValueError('Code must be 6 digits (TOTP) or 8 alphanumeric characters (backup code)')


class MFADisableRequest(BaseModel):
    """MFA disable request."""
    password: str


class BackupCodesResponse(BaseModel):
    """Backup codes response."""
    backup_codes: List[str]
