"""
认证相关Schema模型
"""
from pydantic import BaseModel, Field, EmailStr, field_validator
from typing import Optional, List
from .base import BaseSchema


class LoginRequest(BaseSchema):
    """登录请求Schema"""
    username: str = Field(..., description="用户名或邮箱")
    password: str = Field(..., description="密码")
    grant_type: str = Field(default="password", description="授权类型")
    client_id: Optional[str] = Field(None, description="客户端ID")
    remember_me: bool = Field(default=False, description="记住我")


class RegisterRequest(BaseSchema):
    """注册请求Schema"""
    username: str = Field(..., min_length=3, max_length=50, description="用户名")
    email: EmailStr = Field(..., description="邮箱")
    password: str = Field(..., min_length=8, max_length=128, description="密码")
    phone: Optional[str] = Field(None, max_length=20, description="手机号")
    captcha: str = Field(..., description="验证码")
    
    @field_validator("password")
    @classmethod
    def validate_password(cls, v):
        """密码验证"""
        if not any(c.isupper() for c in v):
            raise ValueError("密码必须包含至少一个大写字母")
        if not any(c.islower() for c in v):
            raise ValueError("密码必须包含至少一个小写字母")
        if not any(c.isdigit() for c in v):
            raise ValueError("密码必须包含至少一个数字")
        return v


class TokenResponse(BaseSchema):
    """令牌响应Schema"""
    access_token: str = Field(..., description="访问令牌")
    refresh_token: Optional[str] = Field(None, description="刷新令牌")
    token_type: str = Field(default="Bearer", description="令牌类型")
    expires_in: int = Field(..., description="过期时间(秒)")
    scope: Optional[str] = Field(None, description="权限范围")


class RefreshTokenRequest(BaseSchema):
    """刷新令牌请求Schema"""
    refresh_token: str = Field(..., description="刷新令牌")
    client_id: Optional[str] = Field(None, description="客户端ID")


class LogoutRequest(BaseSchema):
    """登出请求Schema"""
    token: Optional[str] = Field(None, description="访问令牌")
    refresh_token: Optional[str] = Field(None, description="刷新令牌")


class ForgotPasswordRequest(BaseSchema):
    """忘记密码请求Schema"""
    email: EmailStr = Field(..., description="邮箱")


class ResetPasswordRequest(BaseSchema):
    """重置密码请求Schema"""
    token: str = Field(..., description="重置令牌")
    new_password: str = Field(..., min_length=8, max_length=128, description="新密码")
    
    @field_validator("new_password")
    @classmethod
    def validate_password(cls, v):
        """密码验证"""
        if not any(c.isupper() for c in v):
            raise ValueError("密码必须包含至少一个大写字母")
        if not any(c.islower() for c in v):
            raise ValueError("密码必须包含至少一个小写字母")
        if not any(c.isdigit() for c in v):
            raise ValueError("密码必须包含至少一个数字")
        return v


class CaptchaResponse(BaseSchema):
    """验证码响应Schema"""
    captcha_id: str = Field(..., description="验证码ID")
    captcha_image: str = Field(..., description="验证码图片(base64)")


class UserInfoResponse(BaseSchema):
    """用户信息响应Schema"""
    id: str = Field(..., description="用户ID")
    username: str = Field(..., description="用户名")
    email: str = Field(..., description="邮箱")
    phone: Optional[str] = Field(None, description="手机号")
    avatar_url: Optional[str] = Field(None, description="头像URL")
    is_active: bool = Field(..., description="是否激活")
    roles: List[str] = Field(default=[], description="角色列表")
    permissions: List[str] = Field(default=[], description="权限列表")


class TokenIntrospectRequest(BaseSchema):
    """令牌内省请求Schema"""
    token: str = Field(..., description="令牌")
    token_type_hint: Optional[str] = Field(None, description="令牌类型提示")


class TokenIntrospectResponse(BaseSchema):
    """令牌内省响应Schema"""
    active: bool = Field(..., description="是否有效")
    client_id: Optional[str] = Field(None, description="客户端ID")
    username: Optional[str] = Field(None, description="用户名")
    scope: Optional[str] = Field(None, description="权限范围")
    exp: Optional[int] = Field(None, description="过期时间戳")
    iat: Optional[int] = Field(None, description="签发时间戳")
    sub: Optional[str] = Field(None, description="主题(用户ID)")
    aud: Optional[str] = Field(None, description="受众(客户端ID)")


class RevokeTokenRequest(BaseSchema):
    """撤销令牌请求Schema"""
    token: str = Field(..., description="令牌")
    token_type_hint: Optional[str] = Field(None, description="令牌类型提示")