from enum import Enum as _Enum
from typing import Literal, Optional, List, Dict, Union

from pydantic import BaseModel, Field, RootModel, field_validator

from app.schemas.common import JsonData


class PluginRuntimeStatus(str, _Enum):
    """插件从源码准备到运行激活的六类状态。"""

    SOURCE_MISSING = "source_missing"
    DEPENDENCY_PENDING = "dependency_pending"
    READY = "ready"
    ACTIVE = "active"
    BLOCKED_BY_POLICY = "blocked_by_policy"
    LOAD_FAILED = "load_failed"


class PluginInstance(BaseModel):
    """持久化一个共享源码插件的独立运行实例。"""

    instance_id: str = Field(description="运行实例 ID，也是配置、数据和路由命名空间")
    source_plugin_id: str = Field(description="提供代码与前端资源的源插件 ID")
    plugin_name: Optional[str] = Field(default=None, description="实例展示名称")
    plugin_desc: Optional[str] = Field(default=None, description="实例展示描述")
    plugin_icon: Optional[str] = Field(default=None, description="实例展示图标")
    mode: Literal["virtual"] = Field(default="virtual", description="实例实现模式")

    @field_validator("instance_id", "source_plugin_id")
    @classmethod
    def validate_plugin_id(cls, value: str) -> str:
        """限制实例标识为可安全用作 Python 类名和路由段的格式。"""
        if not value or not value[0].isalpha() or not value.isalnum():
            raise ValueError("插件 ID 必须以字母开头且只能包含字母和数字")
        if len(value) > 128:
            raise ValueError("插件 ID 长度不能超过 128 个字符")
        return value


class Plugin(BaseModel):
    """
    插件信息
    """
    id: str = None
    # 插件名称
    plugin_name: Optional[str] = None
    # 插件描述
    plugin_desc: Optional[str] = None
    # 插件图标
    plugin_icon: Optional[str] = None
    # 插件版本
    plugin_version: Optional[str] = None
    # 插件标签
    plugin_label: Optional[str] = None
    # 插件作者
    plugin_author: Optional[str] = None
    # 作者主页
    author_url: Optional[str] = None
    # 插件配置项ID前缀
    plugin_config_prefix: Optional[str] = None
    # 加载顺序
    plugin_order: Optional[int] = 0
    # 可使用的用户级别
    auth_level: Optional[int] = 0
    # 是否已安装
    installed: Optional[bool] = False
    # 运行状态
    state: Optional[bool] = False
    # 插件源码、依赖和运行时加载状态
    runtime_status: Optional[PluginRuntimeStatus] = None
    # 是否有详情页面
    has_page: Optional[bool] = False
    # 是否有新版本
    has_update: Optional[bool] = False
    # 主系统版本是否兼容
    system_version_compatible: Optional[bool] = True
    # 主系统版本兼容提示
    system_version_message: Optional[str] = None
    # 主系统版本限定范围
    system_version: Optional[str] = None
    # 是否声明支持通过 GitHub Release 资产安装
    release: Optional[bool] = False
    # 是否本地
    is_local: Optional[bool] = False
    # 仓库地址
    repo_url: Optional[str] = None
    # 安装次数
    install_count: Optional[int] = 0
    # 更新记录
    history: Optional[dict[str, str]] = Field(default_factory=dict)
    # 添加时间，值越小表示越靠后发布
    add_time: Optional[int] = 0
    # 插件公钥
    plugin_public_key: Optional[str] = None
    # 共享代码与前端资源的源插件 ID；普通插件为空
    source_plugin_id: Optional[str] = None
    # 是否为共享源码的虚拟实例
    is_instance: Optional[bool] = False
    # 实例实现模式；存量物理分身为空
    instance_mode: Optional[str] = None


class PluginRuntimeSummary(BaseModel):
    """插件后台收敛状态和前端刷新代次。"""

    ready: bool = Field(description="本轮插件源码、依赖和加载是否已收敛")
    generation: int = Field(description="插件运行状态变化代次")
    pending_count: int = Field(description="仍处于准备阶段的插件数量")
    failed_count: int = Field(description="加载失败或被策略阻止的插件数量")


class PluginCloneRequest(BaseModel):
    """创建虚拟插件分身的请求参数。"""

    suffix: str = Field(
        min_length=1,
        max_length=20,
        pattern=r"^[A-Za-z0-9]+$",
        description="追加到当前插件 ID 后的 ASCII 字母或数字后缀",
    )
    name: str = Field(default="", description="分身展示名称")
    description: str = Field(default="", description="分身展示描述")
    icon: Optional[str] = Field(default=None, description="分身展示图标")
    version: Optional[str] = Field(
        default=None,
        description="兼容旧客户端保留，虚拟分身始终跟随源插件版本",
    )


class PluginDashboard(Plugin):
    """
    插件仪表盘
    """
    id: Optional[str] = None
    # 名称
    name: Optional[str] = None
    # 仪表板key
    key: Optional[str] = None
    # 演染模式
    render_mode: Optional[str] = Field(default="vuetify")
    # 全局配置
    attrs: Optional[dict[str, JsonData]] = Field(default_factory=dict)
    # col列数
    cols: Optional[dict[str, JsonData]] = Field(default_factory=dict)
    # 页面元素
    elements: Optional[List[dict[str, JsonData]]] = Field(default_factory=list)


class PluginSidebarNavItem(BaseModel):
    """
    插件侧栏导航项（前端全页路由）
    """
    plugin_id: str = Field(description="插件 ID")
    nav_key: str = Field(description="导航键，对应 URL 段")
    title: str = Field(description="侧栏标题")
    icon: str = Field(default="mdi-puzzle", description="MDI 图标名")
    section: str = Field(
        description="分组：start / discovery / subscribe / organize / system",
    )
    permission: Optional[str] = Field(
        default=None,
        description="权限：subscribe / discovery / search / manage / admin",
    )
    order: int = Field(default=0, description="同组内排序，越小越靠前")


class PluginRatingRequest(BaseModel):
    """插件评分请求"""

    rating: float = Field(
        ge=0.1,
        le=5.0,
        multiple_of=0.1,
        description="评分，范围 0.1 至 5.0，精确到 0.1",
    )


class PluginRating(BaseModel):
    """插件评分结果"""

    plugin_id: str = Field(description="插件 ID")
    average_rating: float = Field(default=0.0, description="平均评分")
    rating_count: int = Field(default=0, description="评分人数")
    user_rating: Optional[float] = Field(default=None, description="当前安装实例评分")


class PluginRatingMap(RootModel[Dict[str, PluginRating]]):
    """插件 ID 与评分结果的映射。"""


class PluginMemoryInfo(BaseModel):
    """插件内存信息"""
    plugin_id: str = Field(description="插件ID")
    plugin_name: str = Field(description="插件名称")
    plugin_version: str = Field(description="插件版本")
    total_memory_bytes: int = Field(description="总内存使用量(字节)")
    total_memory_mb: float = Field(description="总内存使用量(MB)")
    object_count: int = Field(description="对象数量")
    calculation_time_ms: float = Field(description="计算耗时(毫秒)")
    timestamp: float = Field(description="统计时间戳")
    error: Optional[str] = Field(default=None, description="错误信息")
    object_details: Optional[List[Dict[str, JsonData]]] = Field(default=None, description="大对象详情")


class PluginRemoteInfo(BaseModel):
    """插件模块联邦远程入口。"""

    id: str
    url: str
    name: str
    source_plugin_id: Optional[str] = None


class PluginReleaseItem(BaseModel):
    """可安装的插件 Release 版本。"""

    version: str
    tag_name: str
    name: str
    published_at: Optional[str] = None
    body: str = ""
    asset_name: str
    is_latest: bool = False
    is_current: bool = False


class PluginReleaseData(BaseModel):
    """插件 Release 能力与版本列表。"""

    release_supported: bool = False
    latest_version: Optional[str] = None
    current_version: Optional[str] = None
    items: List[PluginReleaseItem] = Field(default_factory=list)


class PluginFolderConfigData(BaseModel):
    """新版插件文件夹配置（对象格式，含展示配置与插件列表）。"""

    # 文件夹内插件 ID 列表
    plugins: List[str] = Field(default_factory=list)
    # 文件夹排序值
    order: Optional[int] = None
    # 文件夹图标
    icon: Optional[str] = None
    # 文件夹颜色
    color: Optional[str] = None
    # 文件夹渐变
    gradient: Optional[str] = None
    # 文件夹背景
    background: Optional[str] = None
    # 是否显示图标（前端字段为驼峰命名）
    show_icon: Optional[bool] = Field(default=None, alias="showIcon")


class PluginFoldersData(RootModel[Dict[str, Union[List[str], PluginFolderConfigData]]]):
    """插件文件夹与插件配置映射，兼容旧版数组格式与新版对象格式。"""


class PluginDashboardMetaItem(BaseModel):
    """插件仪表板入口摘要。"""

    id: str
    name: Optional[str] = None
    key: Optional[str] = None
