"""资产：测试主机、带外控制器、DUT、固件包。"""
from __future__ import annotations

import datetime as _dt
from typing import Any, Dict, List, Optional

from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, JSON, String, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column

from ..enums import DutStatus, HostStatus, PowerState
from .base import Base, TimestampMixin, pk


class OobController(Base, TimestampMixin):
    """带外控制器。

    独立成表而不是挂在 TestHost 上，因为它的核心价值就是**主机死后独活**：
    它有自己的网络、自己的心跳、自己的生命周期。主机 OFFLINE 时它必须还 ONLINE，
    这个"矛盾"状态是恢复阶梯 L3-L5 可用性的判断依据。
    """

    __tablename__ = "oob_controllers"

    id: Mapped[str] = pk("oob")
    name: Mapped[str] = mapped_column(String(128), nullable=False)
    kind: Mapped[str] = mapped_column(String(32), default="simulated")  # raspberry_pi / jetkvm / pdu / simulated
    endpoint: Mapped[Optional[str]] = mapped_column(String(255))
    # 能力位：{"power": true, "reset": true, "atx": true, "ac": true, "hdmi": true, "temp": true}
    capabilities: Mapped[Dict[str, Any]] = mapped_column(JSON, default=dict)

    status: Mapped[str] = mapped_column(String(16), default=HostStatus.UNKNOWN.value)
    power_state: Mapped[str] = mapped_column(String(16), default=PowerState.UNKNOWN.value)
    last_seen_at: Mapped[Optional[_dt.datetime]] = mapped_column(DateTime)
    temperature_c: Mapped[Optional[float]] = mapped_column()


class TestHost(Base, TimestampMixin):
    """测试主机。环境指纹的主要来源 —— A/B 对比的可比性靠它固定。"""

    __tablename__ = "test_hosts"

    id: Mapped[str] = pk("host")
    name: Mapped[str] = mapped_column(String(128), nullable=False, unique=True)

    os_family: Mapped[str] = mapped_column(String(32), default="linux")   # linux / windows
    os_version: Mapped[Optional[str]] = mapped_column(String(128))
    kernel: Mapped[Optional[str]] = mapped_column(String(128))
    cpu: Mapped[Optional[str]] = mapped_column(String(128))
    motherboard: Mapped[Optional[str]] = mapped_column(String(128))
    bios_version: Mapped[Optional[str]] = mapped_column(String(64))
    agent_version: Mapped[Optional[str]] = mapped_column(String(32))
    ip_address: Mapped[Optional[str]] = mapped_column(String(64))

    status: Mapped[str] = mapped_column(String(16), default=HostStatus.UNKNOWN.value)
    last_heartbeat_at: Mapped[Optional[_dt.datetime]] = mapped_column(DateTime)
    agent_id: Mapped[Optional[str]] = mapped_column(String(32))
    # 只保存 bearer token 的 SHA-256 摘要；原始 token 仅在注册响应中返回一次。
    agent_token: Mapped[Optional[str]] = mapped_column(String(64))

    oob_controller_id: Mapped[Optional[str]] = mapped_column(ForeignKey("oob_controllers.id"))
    # 已安装工具与版本，来自 Agent 的 discover()：{"nvme-cli": "2.8", "fio": "3.36"}
    toolchain: Mapped[Dict[str, Any]] = mapped_column(JSON, default=dict)
    labels: Mapped[Dict[str, Any]] = mapped_column(JSON, default=dict)


class Dut(Base, TimestampMixin):
    """被测设备。

    allow_destructive 是防误盘的第二道信号（第一道是序列号，第三道是系统盘检测）。
    它不给普通 API 改 —— 只能走带审批记录的资产接口，见 ADR-0004。
    """

    __tablename__ = "duts"
    __table_args__ = (UniqueConstraint("serial", name="uq_dut_serial"),)

    id: Mapped[str] = pk("dut")
    serial: Mapped[str] = mapped_column(String(64), nullable=False)
    model: Mapped[str] = mapped_column(String(128), nullable=False)
    vendor: Mapped[Optional[str]] = mapped_column(String(64))
    capacity_gb: Mapped[Optional[int]] = mapped_column(Integer)
    form_factor: Mapped[str] = mapped_column(String(32), default="M.2")   # M.2 / U.2 / E1.S
    interface: Mapped[str] = mapped_column(String(32), default="NVMe")

    current_firmware: Mapped[Optional[str]] = mapped_column(String(64))
    bdf: Mapped[Optional[str]] = mapped_column(String(32))          # PCIe 地址，如 0000:03:00.0
    device_path: Mapped[Optional[str]] = mapped_column(String(64))  # /dev/nvme0n1

    test_host_id: Mapped[Optional[str]] = mapped_column(ForeignKey("test_hosts.id"))
    status: Mapped[str] = mapped_column(String(16), default=DutStatus.IDLE.value)

    # 破坏性测试白名单标记。默认 False —— 安全默认拒绝。
    allow_destructive: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)

    health: Mapped[Dict[str, Any]] = mapped_column(JSON, default=dict)   # SMART 关键项、温度、寿命
    labels: Mapped[Dict[str, Any]] = mapped_column(JSON, default=dict)


class FirmwareArtifact(Base, TimestampMixin):
    """固件包。哈希 + 签名 + 适用型号，缺一样就不可审计。"""

    __tablename__ = "firmware_artifacts"

    id: Mapped[str] = pk("fw")
    version: Mapped[str] = mapped_column(String(64), nullable=False)
    label: Mapped[Optional[str]] = mapped_column(String(64))   # "A" / "B" / "候选版"
    sha256: Mapped[str] = mapped_column(String(64), nullable=False)
    signature: Mapped[Optional[str]] = mapped_column(String(512))
    applicable_models: Mapped[List[Any]] = mapped_column(JSON, default=list)
    flash_tool: Mapped[str] = mapped_column(String(64), default="nvme_cli")
    file_uri: Mapped[Optional[str]] = mapped_column(String(512))
    uploaded_by: Mapped[Optional[str]] = mapped_column(String(64))
