#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：central_simulator.py
模块描述：中控设备模拟器，支持 7 种主题类型上报

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

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

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

logger = logging.getLogger(__name__)


# 中控设备类型映射
CENTRAL_DEVICE_TYPES = {
    "room_online": "会议室在线",
    "device_online": "设备在线",
    "audio": "音频系统",
    "video": "视频系统",
    "control": "控制系统",
    "network": "网络系统",
    "power": "电源系统",
}


class CentralSimulator(BaseSimulator):
    """
    中控设备模拟器

    模拟中控设备，管理多个子设备（灯光、窗帘、投影、空调等），支持：
    - 设备注册与状态上报
    - 子设备状态管理
    - 控制指令响应
    - 场景模式切换

    Attributes:
        _sub_devices (dict): 子设备列表及状态
        _current_scene (str): 当前场景模式
    """

    # 默认子设备配置
    _DEFAULT_SUB_DEVICES = {
        "light_main": {"name": "主灯", "type": "light", "status": "on", "brightness": 80},
        "light_side": {"name": "侧灯", "type": "light", "status": "on", "brightness": 60},
        "curtain_main": {"name": "主窗帘", "type": "curtain", "status": "open", "position": 100},
        "projector": {"name": "投影仪", "type": "projector", "status": "off"},
        "screen": {"name": "投影幕布", "type": "screen", "status": "up"},
        "ac_main": {"name": "空调", "type": "ac", "status": "off", "temperature": 26},
        "amplifier": {"name": "功放", "type": "audio", "status": "off", "volume": 30},
    }

    # 场景模式
    _SCENES = {
        "meeting": {
            "name": "会议模式",
            "actions": {
                "light_main": {"brightness": 100},
                "light_side": {"brightness": 40},
                "curtain_main": {"position": 50},
                "projector": {"status": "on"},
                "screen": {"status": "down"},
                "ac_main": {"status": "on", "temperature": 24},
            }
        },
        "presentation": {
            "name": "演讲模式",
            "actions": {
                "light_main": {"brightness": 30},
                "light_side": {"brightness": 20},
                "curtain_main": {"position": 0},
                "projector": {"status": "on"},
                "screen": {"status": "down"},
                "ac_main": {"status": "on", "temperature": 24},
            }
        },
        "rest": {
            "name": "休息模式",
            "actions": {
                "light_main": {"brightness": 20},
                "light_side": {"brightness": 10},
                "curtain_main": {"position": 100},
                "projector": {"status": "off"},
                "screen": {"status": "up"},
                "ac_main": {"status": "on", "temperature": 26},
            }
        },
        "power_off": {
            "name": "关闭模式",
            "actions": {
                "light_main": {"status": "off"},
                "light_side": {"status": "off"},
                "curtain_main": {"position": 100},
                "projector": {"status": "off"},
                "screen": {"status": "up"},
                "ac_main": {"status": "off"},
                "amplifier": {"status": "off"},
            }
        }
    }

    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,
                 token_api_host: Optional[str] = None):
        super().__init__(device_id, env_config_id, "central", mqtt_manager,
                         report_config, topics, topic_params, token_api_host)
        self._sub_devices = {}
        self._current_scene = "power_off"
        self._init_sub_devices()

    def _init_sub_devices(self) -> None:
        """初始化子设备状态"""
        for dev_id, config in self._DEFAULT_SUB_DEVICES.items():
            self._sub_devices[dev_id] = dict(config)

    def build_register_payload(self) -> dict:
        """构建设备注册消息"""
        return {
            "device_id": self.device_id,
            "device_type": "central_controller",
            "name": f"中控设备-{self.device_id}",
            "model": "CC-8000Pro",
            "version": "V4.1.3",
            "sub_devices": [
                {"id": k, "name": v["name"], "type": v["type"]}
                for k, v in self._DEFAULT_SUB_DEVICES.items()
            ],
            "capabilities": ["sub_device_control", "scene_switch", "timer"]
        }

    def build_status_payload(self) -> dict:
        """
        根据设备类型动态选择消息体构建方法

        支持的设备类型：
        - room_online: 会议室在线
        - device_online: 设备在线
        - audio: 音频系统
        - video: 视频系统
        - control: 控制系统
        - network: 网络系统
        - power: 电源系统

        默认为 device_online（设备在线）。
        """
        device_type = self.topic_params.get("device_type", "device_online")
        builder_method = getattr(self, f"_build_{device_type}_payload", self._build_device_online_payload)
        return builder_method()

    def _build_room_online_payload(self) -> dict:
        """
        构建会议室在线消息体

        消息格式：
        {
            "udid": "uuid",
            "action": "online",
            "value": 1
        }
        """
        return {
            "udid": str(uuid.uuid4()),
            "action": "online",
            "value": 1
        }

    def _build_device_online_payload(self) -> dict:
        """
        构建设备在线消息体

        消息格式：
        {
            "action": "_updatestatus",
            "client_udid": "{会议室编号}",
            "data": [
                {"device_udid": "{设备编号}", "power": 1, "online": 1, "watt": 10000, "run": "在线"},
                {"device_udid": "{设备编号}", "power": 1, "online": 1, "watt": 1000, "run": "在线"}
            ]
        }
        """
        room_id = self.topic_params.get("room_id", self.device_id)
        device_number = self.topic_params.get("device_number", self.device_id)
        return {
            "action": "_updatestatus",
            "client_udid": room_id,
            "data": [
                {"device_udid": device_number, "power": 1, "online": 1, "watt": random.randint(5000, 15000), "run": "在线"},
                {"device_udid": device_number, "power": 1, "online": 1, "watt": random.randint(500, 1500), "run": "在线"}
            ]
        }

    def _build_audio_payload(self) -> dict:
        """
        构建音频系统消息体

        消息格式：
        {
            "action": "_updateaudio",
            "client_udid": "{设备编号}",
            "data": [...]
        }
        """
        device_number = self.topic_params.get("device_number", self.device_id)
        return {
            "action": "_updateaudio",
            "client_udid": device_number,
            "data": [
                {
                    "address": 1,
                    "data_all": {"volume": random.randint(20, 50), "mute": 0},
                    "data_channel": [
                        {"lineType": 1, "num": 1, "status": 1, "volume": random.randint(40, 80), "mute": 0},
                        {"lineType": 1, "num": 2, "status": 1, "volume": random.randint(40, 80), "mute": 0}
                    ],
                    "data_meter": [{"lineType": 1, "num": 1, "dbvalue": random.randint(50, 90)}]
                }
            ]
        }

    def _build_video_payload(self) -> dict:
        """
        构建视频系统消息体

        消息格式：
        {
            "action": "_updatevideo",
            "client_udid": "{设备编号}",
            "data": [...]
        }
        """
        device_number = self.topic_params.get("device_number", self.device_id)
        return {
            "action": "_updatevideo",
            "client_udid": device_number,
            "data": [
                {
                    "address": 1,
                    "data_channel": [
                        {"lineType": 1, "num": 1, "status": random.randint(0, 1)},
                        {"lineType": 1, "num": 2, "status": random.randint(0, 1)}
                    ]
                }
            ]
        }

    def _build_control_payload(self) -> dict:
        """
        构建控制系统消息体

        消息格式：
        {
            "action": "_updatecontrol",
            "client_udid": "{设备编号}",
            "data": [...]
        }
        """
        device_number = self.topic_params.get("device_number", self.device_id)
        return {
            "action": "_updatecontrol",
            "client_udid": device_number,
            "data": [
                {
                    "address": 1,
                    "data_com": [{"lineType": 0, "num": 1, "status": 1, "run": "run success"}],
                    "data_ir": [{"lineType": 1, "num": 1, "status": 1, "run": "run success"}],
                    "data_io": [{"lineType": 2, "num": 1, "status": 1, "run": "run success"}],
                    "data_rel": [{"lineType": 3, "num": 1, "status": 1, "run": "run success"}],
                    "data_bus": [{"lineType": 4, "num": 1, "status": 1, "run": "run success"}],
                    "data_net": [{"lineType": 5, "num": 1, "status": 1, "run": "run success"}]
                }
            ]
        }

    def _build_network_payload(self) -> dict:
        """
        构建网络系统消息体

        消息格式：
        {
            "action": "_updatenetwork",
            "client_udid": "{设备编号}",
            "data": [...]
        }
        """
        device_number = self.topic_params.get("device_number", self.device_id)
        return {
            "action": "_updatenetwork",
            "client_udid": device_number,
            "data": [
                {
                    "address": 1,
                    "data_channel": [
                        {"innum": 1, "status": 1, "run": "Good network"},
                        {"innum": 2, "status": 1, "run": "Good network"}
                    ]
                }
            ]
        }

    def _build_power_payload(self) -> dict:
        """
        构建电源系统消息体

        消息格式：
        {
            "action": "_updatepower",
            "client_udid": "{设备编号}",
            "data": [...]
        }
        """
        device_number = self.topic_params.get("device_number", self.device_id)
        return {
            "action": "_updatepower",
            "client_udid": device_number,
            "data": [
                {
                    "address": 1,
                    "data_channel": [
                        {"innum": 1, "status": 1, "power": 1, "level": round(random.uniform(1.0, 2.0), 1)},
                        {"innum": 2, "status": 1, "power": 1, "level": round(random.uniform(1.0, 2.0), 1)}
                    ]
                }
            ]
        }

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

        支持的指令：
        - control_sub_device: 控制子设备
        - switch_scene: 切换场景模式
        - control_all: 批量控制
        """
        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 == "control_sub_device":
                sub_id = payload.get("sub_device_id", "")
                action = payload.get("action", {})
                success = self._control_sub_device(sub_id, action)
                self._notify_report(response_topic, {
                    "device_id": self.device_id,
                    "command": "control_sub_device",
                    "sub_device_id": sub_id,
                    "result": "success" if success else "failed",
                    "message": f"子设备{'控制成功' if success else '控制失败'}: {sub_id}"
                })

            elif command == "switch_scene":
                scene = payload.get("scene", "")
                if scene in self._SCENES:
                    self._apply_scene(scene)
                    self._notify_report(response_topic, {
                        "device_id": self.device_id,
                        "command": "switch_scene",
                        "scene": scene,
                        "scene_name": self._SCENES[scene]["name"],
                        "result": "success"
                    })
                else:
                    self._notify_report(response_topic, {
                        "device_id": self.device_id,
                        "command": "switch_scene",
                        "scene": scene,
                        "result": "failed",
                        "message": f"未知场景: {scene}"
                    })

            elif command == "control_all":
                action = payload.get("action", {})
                all_status = payload.get("status", "")
                if all_status == "on":
                    for sub_id in self._sub_devices:
                        self._sub_devices[sub_id]["status"] = "on"
                elif all_status == "off":
                    for sub_id in self._sub_devices:
                        self._sub_devices[sub_id]["status"] = "off"
                self._notify_report(response_topic, {
                    "device_id": self.device_id,
                    "command": "control_all",
                    "result": "success",
                    "message": f"批量控制成功: {all_status}"
                })

            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 _control_sub_device(self, sub_id: str, action: dict) -> bool:
        """
        控制单个子设备

        Args:
            sub_id: 子设备 ID
            action: 控制动作

        Returns:
            bool: 是否成功
        """
        if sub_id not in self._sub_devices:
            return False

        device = self._sub_devices[sub_id]
        for key, value in action.items():
            if key in device:
                device[key] = value
            elif key == "status" and value in ("on", "off"):
                device["status"] = value

        # 上报子设备状态变更
        sub_topic = f"{self.get_topic_prefix()}/{self.device_id}/sub_status"
        self.mqtt.publish(self.env_config_id, sub_topic, {
            "device_id": self.device_id,
            "sub_device_id": sub_id,
            "status": device.get("status"),
            "action": action,
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
        })
        return True

    def _apply_scene(self, scene: str) -> None:
        """
        应用场景模式

        Args:
            scene: 场景名称
        """
        self._current_scene = scene
        scene_config = self._SCENES.get(scene, {})
        actions = scene_config.get("actions", {})

        for sub_id, action in actions.items():
            if sub_id in self._sub_devices:
                self._sub_devices[sub_id].update(action)

        # 上报场景切换
        scene_topic = f"{self.get_topic_prefix()}/{self.device_id}/scene"
        self.mqtt.publish(self.env_config_id, scene_topic, {
            "device_id": self.device_id,
            "scene": scene,
            "scene_name": scene_config.get("name", ""),
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
        })

    def trigger_scene(self, scene: str) -> bool:
        """
        手动触发场景切换

        Args:
            scene: 场景名称

        Returns:
            bool: 是否成功
        """
        if scene not in self._SCENES:
            return False
        self._apply_scene(scene)
        return True