"""
PROTOCOL_MODEL:
ACTION(1) + PROTOCOL_BODY(BSON)
"""

from enum import Enum
from typing import Any, Optional, Type

from pydantic import BaseModel, Field


class ActionEnum(int, Enum):
    """动作枚举"""

    def __new__(cls, value: int, model: Optional[Type[BaseModel]]):
        obj = int.__new__(cls, value)
        obj._value_ = value
        obj.model = model
        return obj

    def __init__(self, value: int, model: Optional[Type[BaseModel]]):
        self.model = model
        super().__init__(value)


class Method(BaseModel):
    """计算方法"""

    name: str = Field(description="方法名称")
    cpu_usage: int = Field(description="CPU占用数")
    gpu_usage: int = Field(description="GPU占用数")


class OnlineModel(BaseModel):
    """上线模型"""

    access_id: str = Field(description="访问ID")
    access_token: str = Field(description="访问令牌")
    platform_tag: str = Field(description="平台标签")
    node_version: str = Field(description="计算端节点版本")
    cpu_resource: int = Field(description="CPU资源")
    gpu_resource: int = Field(description="GPU资源")
    enabled_methods: list[Method] = Field(description="启用方法")


class PushTaskModel(BaseModel):
    """推送计算任务模型"""

    task_id: str = Field(description="任务ID")
    method: str = Field(description="方法")
    parameters: dict[str, Any] = Field(description="参数")


class ReturnAnswerModel(BaseModel):
    """返回计算结果模型"""

    task_id: str = Field(description="任务ID")
    completed: bool = Field(description="是否完成")
    result: Any = Field(description="结果")


class PingModel(BaseModel):
    """心跳模型"""

    report_time: int = Field(description="报告时间")
    cpu_usage: float = Field(description="CPU使用率")
    memory_usage: float = Field(description="内存使用率")
    disk_usage: float = Field(description="磁盘使用率")
    load_average: float = Field(description="负载平均值")
    calculator_worker_num: int = Field(description="计算工作进程数量")
    calculator_load: float = Field(description="计算工作进程负载")
    calculator_free: int = Field(description="计算工作进程空闲数")


class ReadLogModel(BaseModel):
    """读取日志模型"""

    logger: str = Field(description="日志器")
    offset: int = Field(description="起始字节数")
    limit: int = Field(description="限制返回字节数")


class ReturnLogger(BaseModel):
    """返回日志器"""

    logger: str = Field(description="日志器")
    total_size: int = Field(description="日志文件大小")


class ReturnLoggerModel(BaseModel):
    """返回日志器模型"""

    loggers: list[ReturnLogger] = Field(description="日志器")


class ReturnLogsModel(BaseModel):
    """返回日志模型"""

    data: bytes = Field(description="日志数据")


class SyncDataLogModel(BaseModel):
    """同步数据日志模型"""

    filename: str = Field(description="文件名")
    is_ok: bool = Field(description="是否成功")
    latest_tag: str = Field(description="最新标签")
    error_message: str = Field(description="错误信息")


class DatasetStatusItem(BaseModel):
    """数据集状态条目"""

    dataset: str = Field(description="数据集名称，如 STK_DATA / CB_DATA")
    category: str = Field(description="分类：snapshot_history / realtime_quotes")
    data_time: str = Field(description="最新业务时间（YYYY-MM-DD 或 ISO 8601）")
    synced_at: str = Field(description="同步完成时间（ISO 8601）")
    status: str = Field(description="状态：ready / syncing / failed")
    file_etag: str = Field(description="COS ETag（实时行情可为空）")


class ReportDatasetStatusModel(BaseModel):
    """数据集状态上报模型"""

    datasets: list[DatasetStatusItem] = Field(description="数据集状态列表")


class LockResourceModel(BaseModel):
    """锁定资源模型"""

    cpu_resource: int = Field(description="CPU资源")
    gpu_resource: int = Field(description="GPU资源")


class FinishOrCancelTaskModel(BaseModel):
    """完成或取消计算任务模型"""

    task_id: str = Field(description="任务ID")
    method: str = Field(description="方法")


class UpgradeModel(BaseModel):
    """更新模型"""

    version: Optional[str] = Field(default=None, description="版本号")


class NodeAction(ActionEnum):
    """节点动作"""

    ONLINE = 200, OnlineModel  # 上线
    PING = 201, PingModel  # 心跳
    RETURN_ANSWER = 202, ReturnAnswerModel  # 返回计算结果
    RETURN_LOGGERS = 203, ReturnLoggerModel  # 返回日志器
    RETURN_LOGS = 204, ReturnLogsModel  # 返回日志
    SYNC_DATA_LOG = 205, SyncDataLogModel  # 同步数据日志
    LOCK_RESOURCE = 206, LockResourceModel  # 锁定资源
    FINISHED_TASK = 207, FinishOrCancelTaskModel  # 释放资源
    CANCELLED_TASK = 208, FinishOrCancelTaskModel  # 任务取消
    REPORT_DATASET_STATUS = 209, ReportDatasetStatusModel  # 数据集状态上报


class EndpointAction(ActionEnum):
    """端点动作"""

    PUSH_TASK = 100, PushTaskModel  # 推送计算任务
    PONG = 101, None  # 回应心跳
    RESTART = 102, None  # 要求重启
    UPGRADE = 103, UpgradeModel  # 要求更新
    OFFLINE = 104, None  # 要求下线
    READ_LOGGERS = 105, None  # 读取日志器
    READ_LOG = 106, ReadLogModel  # 读取日志
    CANCEL_TASK = 107, FinishOrCancelTaskModel  # 取消计算任务
