#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：central_simulator.py
模块描述：中控设备模拟器，模拟灯光/窗帘/投影等设备控制

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

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

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

logger = logging.getLogger(__name__)


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):
        super().__init__(device_id, env_config_id, "central", mqtt_manager,
                         report_config, topics, topic_params)
        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:
        """构建设备状态上报消息"""
        sub_status = {}
        for dev_id, config in self._sub_devices.items():
            sub_status[dev_id] = {
                "status": config.get("status", "off"),
                "brightness": config.get("brightness"),
                "position": config.get("position"),
                "temperature": config.get("temperature"),
                "volume": config.get("volume"),
            }

        return {
            "device_id": self.device_id,
            "status": "online",
            "current_scene": self._current_scene,
            "scene_name": self._SCENES.get(self._current_scene, {}).get("name", ""),
            "sub_device_count": len(self._sub_devices),
            "sub_devices": sub_status,
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
        }

    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