#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：device_sim.py
模块描述：设备模拟模块数据库模型定义

作者：czj
创建日期：2026-07-29
最后修改：2026-07-29
"""

from datetime import datetime
from typing import Optional
from sqlalchemy import String, Text, Integer, Boolean, DateTime, JSON
from sqlalchemy.orm import Mapped, mapped_column

from app.database import Base


class EnvConfig(Base):
    """
    MQTT 环境配置数据库模型

    管理 MQTT Broker 连接参数，是设备模拟模块的基础配置。
    每个环境配置包含 Broker 地址、端口、认证信息、主题前缀等。

    Attributes:
        id (str): 配置唯一标识
        name (str): 配置名称
        broker_host (str): Broker 地址
        broker_port (int): 端口号
        username (str): MQTT 用户名
        password_encrypted (str): 密码（加密存储）
        topic_prefix (str): 主题前缀
        use_tls (bool): 是否启用 TLS
        client_id_prefix (str): 客户端 ID 前缀
        status (str): 连接状态 (disconnected/connected/error)
        last_connected_at (datetime): 最后连接时间
        created_at (datetime): 创建时间
        updated_at (datetime): 更新时间
    """

    __tablename__ = "device_env_configs"

    id: Mapped[str] = mapped_column(String(64), primary_key=True)
    name: Mapped[str] = mapped_column(String(100), nullable=False, comment="配置名称")
    broker_host: Mapped[str] = mapped_column(String(255), nullable=False, comment="Broker 地址")
    broker_port: Mapped[int] = mapped_column(Integer, default=1883, comment="端口号")
    username: Mapped[Optional[str]] = mapped_column(String(100), nullable=True, comment="MQTT 用户名")
    password_encrypted: Mapped[Optional[str]] = mapped_column(String(500), nullable=True, comment="密码（加密存储）")
    topic_prefix: Mapped[str] = mapped_column(String(200), default="device", comment="主题前缀（已弃用，建议使用 topics）")
    topics: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True, comment="多主题前缀映射，如 {'door': 'device/door', 'paperless': 'device/paperless'}")
    use_tls: Mapped[bool] = mapped_column(Boolean, default=False, comment="是否启用 TLS")
    client_id_prefix: Mapped[str] = mapped_column(String(100), default="sim", comment="客户端 ID 前缀")
    status: Mapped[str] = mapped_column(String(20), default="disconnected", comment="连接状态")
    last_connected_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True, comment="最后连接时间")
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now, comment="创建时间")
    updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now, onupdate=datetime.now, comment="更新时间")


class DeviceSimulator(Base):
    """
    模拟设备数据库模型

    存储模拟设备的基本信息和运行状态。
    支持 5 种设备类型：door(门口屏)、paperless(无纸化)、central(中控)、client(集控客户端)

    Attributes:
        id (str): 设备唯一标识
        env_config_id (str): 关联环境配置 ID
        device_type (str): 设备类型
        device_name (str): 模拟设备名称
        device_id (str): 模拟设备 ID（MQTT 主题中使用）
        status (str): 运行状态 (stopped/running/error)
        auto_reconnect (bool): 是否自动重连
        metadata (dict): 设备自定义属性
        last_reported_at (datetime): 最后上报时间
        total_reports (int): 累计上报次数
        created_at (datetime): 创建时间
        updated_at (datetime): 更新时间
    """

    __tablename__ = "device_simulators"

    id: Mapped[str] = mapped_column(String(64), primary_key=True)
    env_config_id: Mapped[str] = mapped_column(String(64), nullable=False, comment="关联环境配置 ID")
    device_type: Mapped[str] = mapped_column(String(50), nullable=False, comment="设备类型")
    device_name: Mapped[str] = mapped_column(String(200), nullable=False, comment="模拟设备名称")
    device_id: Mapped[str] = mapped_column(String(200), nullable=False, comment="模拟设备 ID")
    status: Mapped[str] = mapped_column(String(20), default="stopped", comment="运行状态")
    auto_reconnect: Mapped[bool] = mapped_column(Boolean, default=True, comment="是否自动重连")
    extra_attrs: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True, comment="设备自定义属性")
    last_reported_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True, comment="最后上报时间")
    total_reports: Mapped[int] = mapped_column(Integer, default=0, comment="累计上报次数")
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now, comment="创建时间")
    updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now, onupdate=datetime.now, comment="更新时间")


class ReportLog(Base):
    """
    上报记录数据库模型

    记录设备上报和接收的消息历史。

    Attributes:
        id (str): 记录唯一标识
        device_id (str): 关联模拟设备 ID
        topic (str): MQTT 主题
        payload (dict): 上报数据内容
        direction (str): 方向 (publish/subscribe)
        status (str): 发送状态 (success/failed)
        error_message (str): 错误信息
        created_at (datetime): 创建时间
    """

    __tablename__ = "device_report_logs"

    id: Mapped[str] = mapped_column(String(64), primary_key=True)
    device_id: Mapped[str] = mapped_column(String(64), nullable=False, comment="关联模拟设备 ID")
    topic: Mapped[str] = mapped_column(String(500), nullable=False, comment="MQTT 主题")
    payload: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True, comment="上报数据内容")
    direction: Mapped[str] = mapped_column(String(10), default="publish", comment="方向")
    status: Mapped[str] = mapped_column(String(20), default="success", comment="发送状态")
    error_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True, comment="错误信息")
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now, comment="创建时间")