from typing import Optional

from pydantic import BaseModel, Field, ConfigDict
from typing_extensions import TypedDict

from app.schemas.common import JsonData


class UserPermissions(TypedDict, total=False):
    """用户分类权限及可动态扩展的功能级权限。"""

    discovery: bool  # 发现功能分类权限
    search: bool  # 资源搜索分类权限
    subscribe: bool  # 订阅管理分类权限
    manage: bool  # 系统管理分类权限
    admin: bool  # 管理员入口标识，实际授权仍由超级用户身份决定
    features: dict[str, bool]  # 功能键到启用状态的映射


# Shared properties
class UserBase(BaseModel):
    """用户公共资料、权限和个性化设置。"""

    # 用户名
    name: str
    # 邮箱，未启用
    email: Optional[str] = None
    # 状态
    is_active: Optional[bool] = True
    # 超级管理员
    is_superuser: bool = False
    # 头像
    avatar: Optional[str] = None
    # 是否开启二次验证
    is_otp: Optional[bool] = False
    # 权限
    permissions: Optional[UserPermissions] = Field(default_factory=dict)
    # 个性化设置
    settings: Optional[dict[str, JsonData]] = Field(default_factory=dict)

    model_config = ConfigDict(from_attributes=True)


# Properties to receive via API on creation
class UserCreate(UserBase):
    """创建用户时接收的资料和初始凭据。"""

    name: str
    email: Optional[str] = None
    password: Optional[str] = None
    settings: Optional[dict[str, JsonData]] = Field(default_factory=dict)
    permissions: Optional[UserPermissions] = Field(default_factory=dict)


# Properties to receive via API on update
class UserUpdate(UserBase):
    """更新用户时接收的完整资料。"""

    id: int
    name: str
    email: Optional[str] = None
    password: Optional[str] = None
    settings: Optional[dict[str, JsonData]] = Field(default_factory=dict)
    permissions: Optional[UserPermissions] = Field(default_factory=dict)


class UserInDBBase(UserBase):
    """包含数据库主键的用户公共记录。"""

    id: Optional[int] = None

    model_config = ConfigDict(from_attributes=True)


# Additional properties to return via API
class User(UserInDBBase):
    """对 API 调用方公开的用户资料。"""

    name: str
    email: Optional[str] = None


# Additional properties stored in DB
class UserInDB(UserInDBBase):
    """包含密码哈希的内部用户记录。"""

    hashed_password: str


class AuthProviderRemote(BaseModel):
    """插件认证提供方的远程组件信息。"""

    id: str
    url: str
    name: str


class AuthProviderInfo(BaseModel):
    """匿名登录页可展示的认证提供方摘要。"""

    id: str
    type: str
    name: str
    enabled: bool = True
    method: Optional[str] = None
    icon: Optional[str] = None
    component: Optional[str] = None
    plugin_id: Optional[str] = None
    remote: Optional[AuthProviderRemote] = None
