"""admin 设备存活监控 schemas(只读)。

数据源 device_liveness 表(见 app/models/device.py)。online / display_state /
offline_seconds 为后端按 HEARTBEAT_TIMEOUT_MINUTES 阈值派生的瞬态字段(非 DB 列),
在 repo 里算好挂到行上,供 from_attributes 读出。
"""
from __future__ import annotations

from datetime import datetime

from pydantic import BaseModel, ConfigDict


class DeviceLivenessItem(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: int
    user_id: int
    # join user 取(瞬态;理论上 user 恒存在,留空仅防脏数据)
    phone: str | None = None
    nickname: str | None = None

    device_id: str
    device_model: str | None = None      # 由 device_id 解析(device_<机型>_<hash>);非 DB 列
    platform: str
    app_version: str | None = None
    registration_id: str | None = None  # 非空 = 拿到极光 token、可推送

    ever_protected: bool                 # 是否开过无障碍(=该设备对功能有意义)
    first_protected_at: datetime | None = None   # 首次开无障碍时刻(老设备为 null)
    last_heartbeat_at: datetime | None = None
    last_report_protection_on: bool      # 心跳里上报的无障碍开关(恒 true,仅观测)
    liveness_state: str                  # unknown / alive / silent(当前未用) / notified
    notified_at: datetime | None = None
    kill_alert_pending: bool             # 掉线召回待客户端 ack(与 state 解耦)
    created_at: datetime
    updated_at: datetime

    # ===== 后端派生(非 DB 列)=====
    online: bool = False                 # ever_protected 且距上次心跳 ≤ 阈值
    # 显示态:online=在线 / offline=已掉线 / never=从未启用(没开过无障碍)
    display_state: str = "never"
    # 掉线时长(秒):仅 offline 时有值;在线 / 从未启用为 None
    offline_seconds: int | None = None


class DeviceLivenessStats(BaseModel):
    """顶部卡片:总设备数 + 在线 / 已掉线 / 未启用(按心跳阈值派生的 operator 口径,
    不暴露内部状态机 unknown/alive/silent/notified)。"""

    total: int
    online: int
    offline: int
    never: int
