#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：paperless_simulator.py
模块描述：无纸化会议设备模拟器

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

import json
import logging
import random
import time
from datetime import datetime
from typing import Optional

from app.simulators.base_simulator import BaseSimulator
from app.services.mqtt_manager import MqttManager

logger = logging.getLogger(__name__)


class PaperlessSimulator(BaseSimulator):
    """
    无纸化会议设备模拟器

    模拟无纸化会议终端（华为平板 BAH3-W59），支持：
    - 设备注册与状态上报（rebootResponseTopic + /uams/android/broadcast）
    - 参会人员签到/签退
    - 会议文件同步状态
    - 投屏开始/结束/异常
    - 会议状态变化

    Attributes:
        _meeting_status (str): 会议状态 (idle/active/ended)
        _signed_in (bool): 是否已签到
        _file_sync_progress (int): 文件同步进度 (0-100)
        _screen_sharing (bool): 是否正在投屏
    """

    # 会议议题列表
    _AGENDA_ITEMS = [
        "会议开场致辞",
        "上季度工作总结",
        "项目进度汇报",
        "技术方案评审",
        "预算审批",
        "下季度计划制定",
        "自由讨论",
        "会议总结"
    ]

    def __init__(self, device_id: str, env_config_id: str,
                 mqtt_manager: MqttManager, report_config: Optional[dict] = None,
                 topics: Optional[dict] = None,
                 topic_params: Optional[dict] = None):
        super().__init__(device_id, env_config_id, "paperless", mqtt_manager,
                         report_config, topics, topic_params)
        self._meeting_status = "idle"
        self._signed_in = False
        self._file_sync_progress = 0
        self._screen_sharing = False
        self._current_agenda = ""

    def build_reboot_response_payload(self) -> dict:
        """
        构建无纸化设备的 rebootResponseTopic 消息体

        无纸化设备与门口屏消息体有差异：
        - appName: "无纸化2.0"
        - deviceModel: "BAH3-W59"（华为平板）
        - wgtVersion: "0.0.31"
        - buildInfo: 空字符串
        - faceVersion: 空字符串
        - authCode: 格式如 "ANP-P7J-0020"
        - conferenceName: 会议室名称

        Returns:
            dict: reboot 响应消息内容
        """
        # 从 topic_params 获取动态参数（与门口屏一致，仅前缀 AND→ANP）
        conference_name = self.topic_params.get("conference_name", "测试会议室1")
        # 无纸化授权码：优先使用 paperless_token_prefix，否则将门口屏的 AND 前缀替换为 ANP
        paperless_prefix = self.topic_params.get("paperless_token_prefix", "")
        if paperless_prefix:
            # 使用环境配置中的无纸化前缀 + 序号
            token_start = int(self.topic_params.get("paperless_token_start", 1))
            token_seq = hash(self.device_id) % 10000 + token_start
            auth_code = f"{paperless_prefix}-{token_seq:04d}"
        else:
            # 回退：将门口屏的 AND 前缀替换为 ANP
            app_token = self.topic_params.get("app_token", "AND-518-0001")
            auth_code = app_token.replace("AND-", "ANP-", 1)

        # 内存和存储（华为平板 BAH3-W59 配置）
        total_mem = 3781
        free_mem = random.randint(1000, 2500)
        internal_total = 53768880128  # 约 50GB
        internal_free = random.randint(20000000000, 40000000000)

        # 系统时间
        sys_date_obj = datetime.now()
        sys_date = sys_date_obj.strftime("%a %b %d %H:%M:%S GMT+08:00 %Y")
        sys_date_str = sys_date_obj.strftime("%Y-%m-%d %H:%M:%S")

        # 运行时长（模拟）
        seed = hash(self.device_id) % 200000  # 最大约 55 小时
        hours = seed // 3600
        minutes = (seed % 3600) // 60
        seconds = seed % 60
        sys_elapsed_realtime = f"{hours}:{minutes:02d}:{seconds:02d}"

        # 传感器列表（华为平板传感器）
        sensors = [
            "accelerometer-kx021",
            "mag-mmc5603",
            "orientation",
            "als-tcs3707",
            "gravity",
            "linear Acceleration",
            "rotation Vector",
            "HALL sensor",
            "uncalibrated Magnetic Field",
            "significant Motion",
            "geomagnetic Rotation Vector",
            "phonecall sensor"
        ]

        # 构建 result 对象（无纸化设备特有格式）
        result_data = {
            "result": {
                "buildInfo": "",  # 无纸化设备此字段为空
                "faceVersion": "",  # 无纸化设备此字段为空
                "wgtVersion": "0.0.31",
                "deviceModel": "Pad-10Pro",
                "abiList": ["arm64-v8a", "armeabi-v7a", "armeabi"],
                "androidId": self.device_id,
                "appName": "无纸化2.0",
                "appPackageName": "com.ubains.local.gviewer",
                "appVersion": 414,
                "appVersionName": "1.3.414",
                "battery": round(random.uniform(0.5, 1.0), 2),
                "bluetoothEnabled": False,
                "camerasCount": 2,
                "charging": random.choice([True, False]),
                "density": 2,
                "freeAndTotalMemory": f"{free_mem}M/{total_mem}M",
                "internalAvailableSize": internal_free,
                "internalTotalSize": internal_total,
                "ipAddress": f"192.168.{random.randint(1, 254)}.{random.randint(1, 254)}",
                "macAddress": ":".join([f"{random.randint(0, 255):02X}" for _ in range(6)]),
                "networkType": "NETWORK_WIFI",
                "processCpuUsage": "ERR",  # 真实设备返回 ERR
                "resolution": "2000x1200",
                "romName": "huawei",
                "rooted": False,
                "sdkVersionCode": 29,
                "sdkVersionName": "10",
                "sysDate": sys_date,
                "sysDateStr": sys_date_str,
                "sysElapsedRealtime": sys_elapsed_realtime,
                "sysLanguage": "zh",
                "sysSupportedSensors": sensors,
                "authCode": auth_code,
                "conferenceName": conference_name
            }
        }

        # 外层消息结构
        return {
            "method": "/system/readSystemInfo",
            "clientId": self.device_id,
            "result": json.dumps(result_data, ensure_ascii=False)
        }

    def build_heartbeat_payload(self) -> dict:
        """
        构建 /uams/android/broadcast 心跳消息体

        Returns:
            dict: 心跳消息内容
        """
        return {
            "type": "heartbeat",
            "clientId": self.device_id,
            "appId": "com.ubains.local.gviewer",
            "deviceId": self.device_id
        }

    def build_register_payload(self) -> dict:
        """构建设备注册消息"""
        return {
            "device_id": self.device_id,
            "device_type": "paperless_terminal",
            "name": f"无纸化终端-{self.device_id}",
            "model": "MT-21P",
            "version": "V3.2.1",
            "screen_size": "21.5英寸",
            "resolution": "1920x1080",
            "capabilities": ["sign_in", "file_sync", "screen_share", "meeting_control"]
        }

    def build_status_payload(self) -> dict:
        """构建设备状态上报消息"""
        return {
            "device_id": self.device_id,
            "status": "online",
            "meeting_status": self._meeting_status,
            "signed_in": self._signed_in,
            "screen_sharing": self._screen_sharing,
            "cpu_usage": random.randint(20, 80),
            "memory_usage": random.randint(30, 70),
            "disk_usage": random.randint(20, 60),
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
        }

    def _on_command(self, topic: str, payload: dict) -> None:
        """
        处理平台下发的指令

        支持的指令：
        - start_meeting: 开始会议
        - end_meeting: 结束会议
        - start_screen_share: 开始投屏
        - stop_screen_share: 停止投屏
        - sync_file: 同步文件
        """
        try:
            command = payload.get("command", "")
            logger.info(f"无纸化设备收到指令: device_id={self.device_id}, command={command}")

            # 记录接收到的平台下发指令（direction=subscribe）
            command_topic = f"{self.get_topic_prefix()}/{self.device_id}/command"
            self._notify_report(
                command_topic,
                payload,
                direction="subscribe",
                status="success"
            )

            response_topic = f"{self.get_topic_prefix()}/{self.device_id}/command_response"

            if command == "start_meeting":
                self._meeting_status = "active"
                self._current_agenda = self._AGENDA_ITEMS[0]
                self._file_sync_progress = 0
                self._notify_report(response_topic, {
                    "device_id": self.device_id,
                    "command": "start_meeting",
                    "result": "success",
                    "meeting_name": f"会议-{time.strftime('%Y%m%d')}"
                })

            elif command == "end_meeting":
                self._meeting_status = "ended"
                self._signed_in = False
                self._screen_sharing = False
                self._notify_report(response_topic, {
                    "device_id": self.device_id,
                    "command": "end_meeting",
                    "result": "success",
                    "duration_minutes": random.randint(30, 120)
                })

            elif command == "start_screen_share":
                self._screen_sharing = True
                self._notify_report(response_topic, {
                    "device_id": self.device_id,
                    "command": "start_screen_share",
                    "result": "success",
                    "share_content": self._current_agenda or "桌面"
                })

            elif command == "stop_screen_share":
                self._screen_sharing = False
                self._notify_report(response_topic, {
                    "device_id": self.device_id,
                    "command": "stop_screen_share",
                    "result": "success"
                })

            elif command == "sync_file":
                # 模拟文件同步
                self._file_sync_progress = 0
                self._simulate_file_sync()
                self._notify_report(response_topic, {
                    "device_id": self.device_id,
                    "command": "sync_file",
                    "result": "success",
                    "message": "文件同步已开始"
                })

            else:
                self._notify_report(response_topic, {
                    "device_id": self.device_id,
                    "command": command,
                    "result": "unknown",
                    "message": f"不支持的指令: {command}"
                })

        except Exception as e:
            logger.error(f"无纸化设备指令处理异常: {e}")

    def _simulate_file_sync(self) -> None:
        """模拟文件同步进度"""
        import threading as t

        def _sync():
            for i in range(1, 11):
                if not self._running:
                    break
                time.sleep(1)
                self._file_sync_progress = i * 10
                # 上报同步进度
                if self._has_real_topics:
                    # 使用真实主题，找 meeting_message 或第一个 publish 主题
                    topic = self.get_resolved_topic("meeting_message")
                    if not topic:
                        publish_topics = self.get_publish_topics()
                        topic = publish_topics[0]["topic"] if publish_topics else self.get_topic_prefix()
                else:
                    topic = f"{self.get_topic_prefix()}/{self.device_id}/file_sync"
                self.mqtt.publish(self.env_config_id, topic, {
                    "device_id": self.device_id,
                    "progress": self._file_sync_progress,
                    "file_name": f"meeting_materials_{time.strftime('%Y%m%d')}.pdf",
                    "file_size_mb": random.randint(5, 50),
                    "status": "syncing" if i < 10 else "completed"
                })

        t.Thread(target=_sync, daemon=True).start()

    def trigger_sign_in(self, user_name: Optional[str] = None) -> bool:
        """
        触发签到上报

        Args:
            user_name: 签到用户名称

        Returns:
            bool: 是否上报成功
        """
        self._signed_in = True
        payload = {
            "device_id": self.device_id,
            "action": "sign_in",
            "user_name": user_name or f"参会人员_{random.randint(1, 50)}",
            "department": random.choice(["研发部", "产品部", "测试部", "运维部", "市场部"]),
            "sign_time": time.strftime("%Y-%m-%d %H:%M:%S"),
            "meeting_name": f"会议-{time.strftime('%Y%m%d')}"
        }
        return self.report("signin", payload)

    def trigger_sign_out(self) -> bool:
        """触发签退上报"""
        self._signed_in = False
        payload = {
            "device_id": self.device_id,
            "action": "sign_out",
            "sign_time": time.strftime("%Y-%m-%d %H:%M:%S")
        }
        return self.report("signin", payload)

    def trigger_screen_status(self, status: str = "sharing") -> bool:
        """
        触发投屏状态上报

        Args:
            status: 投屏状态 (sharing/stopped/error)

        Returns:
            bool: 是否上报成功
        """
        payloads = {
            "sharing": {
                "device_id": self.device_id,
                "status": "sharing",
                "content": self._current_agenda or "桌面",
                "start_time": time.strftime("%Y-%m-%d %H:%M:%S")
            },
            "stopped": {
                "device_id": self.device_id,
                "status": "stopped",
                "reason": "normal",
                "duration_seconds": random.randint(60, 600)
            },
            "error": {
                "device_id": self.device_id,
                "status": "error",
                "error_code": "SCREEN_001",
                "error_message": "投屏连接中断"
            }
        }
        payload = payloads.get(status, payloads["sharing"])
        return self.report("screen", payload)