#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
模块名称：topic_templates.py
模块描述：设备类型 MQTT 主题模板定义

每种设备类型定义一组固定主题模板，包含动态参数占位符。
模拟器启动时用 topic_params 替换占位符，生成实际主题。

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

from typing import Dict, List

# 主题模板结构说明：
# - key: 模板唯一标识
# - template: 主题路径模板（含 {param} 占位符）
# - label: 中文标签
# - params: 需要填写的动态参数名列表
# - param_labels: 参数名 -> 中文标签映射
# - param_defaults: 参数名 -> 默认值映射
# - direction: publish（上报）/ subscribe（接收/订阅）

DEVICE_TOPIC_TEMPLATES: Dict[str, List[dict]] = {
    "door": [
        # ========== 上报主题（publish）==========
        {
            "key": "reboot_response",
            "template": "rebootResponseTopic",
            "label": "重启响应",
            "params": [],
            "param_labels": {},
            "param_defaults": {},
            "direction": "publish",
        },
        {
            "key": "android_broadcast",
            "template": "/uams/android/broadcast",
            "label": "安卓广播",
            "params": ["device_id"],
            "param_labels": {"device_id": "设备ID"},
            "param_defaults": {"device_id": "DS001"},
            "direction": "publish",
        },
        # ========== 订阅主题（subscribe）==========
        {
            "key": "conference",
            "template": "/meeting/conference/{room_id}/",
            "label": "会议信息",
            "params": ["room_id"],
            "param_labels": {"room_id": "会议室编号"},
            "param_defaults": {"room_id": "A101"},
            "direction": "subscribe",
        },
        {
            "key": "material_client",
            "template": "/material/client/{device_id}/",
            "label": "物料客户端",
            "params": ["device_id"],
            "param_labels": {"device_id": "设备ID"},
            "param_defaults": {"device_id": "DS001"},
            "direction": "subscribe",
        },
        {
            "key": "conference_service_request",
            "template": "/iot/v1/conference/service/request/{company_id}/{room_id}/",
            "label": "会议服务请求",
            "params": ["company_id", "room_id"],
            "param_labels": {"company_id": "公司编号", "room_id": "会议室编号"},
            "param_defaults": {"company_id": "001", "room_id": "A101"},
            "direction": "subscribe",
        },
        {
            "key": "face_extract",
            "template": "/doorscreen/v5/{device_id}/face/extractFeature/imageBase64/list/up",
            "label": "人脸特征提取",
            "params": ["device_id"],
            "param_labels": {"device_id": "设备ID"},
            "param_defaults": {"device_id": "DS001"},
            "direction": "subscribe",
        },
        {
            "key": "radar_event",
            "template": "/iot/v1/device/event/request/millimeterhaveRadar/{room_id}/",
            "label": "毫米波雷达事件",
            "params": ["room_id"],
            "param_labels": {"room_id": "会议室编号"},
            "param_defaults": {"room_id": "A101"},
            "direction": "subscribe",
        },
        {
            "key": "meeting_message",
            "template": "/meeting/message/{room_id}/",
            "label": "会议消息",
            "params": ["room_id"],
            "param_labels": {"room_id": "会议室编号"},
            "param_defaults": {"room_id": "A101"},
            "direction": "subscribe",
        },
        {
            "key": "device_service_request",
            "template": "/iot/v1/device/service/request/{company_id}/{device_id}/",
            "label": "设备服务请求",
            "params": ["company_id", "device_id"],
            "param_labels": {"company_id": "公司编号", "device_id": "设备ID"},
            "param_defaults": {"company_id": "001", "device_id": "DS001"},
            "direction": "subscribe",
        },
    ],
    "paperless": [
        # ========== 上报主题（publish）==========
        {
            "key": "reboot_response",
            "template": "rebootResponseTopic",
            "label": "重启响应",
            "params": [],
            "param_labels": {},
            "param_defaults": {},
            "direction": "publish",
        },
        {
            "key": "android_broadcast",
            "template": "/uams/android/broadcast",
            "label": "安卓广播",
            "params": ["device_id"],
            "param_labels": {"device_id": "设备ID"},
            "param_defaults": {"device_id": "PS001"},
            "direction": "publish",
        },
        {
            "key": "meeting_message",
            "template": "/meeting/message/{room_id}/",
            "label": "会议消息",
            "params": ["room_id"],
            "param_labels": {"room_id": "会议室编号"},
            "param_defaults": {"room_id": "A101"},
            "direction": "publish",
        },
        {
            "key": "meeting_control",
            "template": "/iot/v1/meeting/service/request/meetingControl/{company_id}/{mid}/",
            "label": "会议控制",
            "params": ["company_id", "mid"],
            "param_labels": {"company_id": "公司编号", "mid": "会议ID"},
            "param_defaults": {"company_id": "001", "mid": "M001"},
            "direction": "publish",
        },
        {
            "key": "android_panel",
            "template": "/androidPanel/",
            "label": "安卓面板",
            "params": [],
            "param_labels": {},
            "param_defaults": {},
            "direction": "publish",
        },
        {
            "key": "paperless_service",
            "template": "/message/paperLessService/callService",
            "label": "无纸化服务调用",
            "params": [],
            "param_labels": {},
            "param_defaults": {},
            "direction": "publish",
        },
        # ========== 订阅主题（subscribe）==========
        {
            "key": "meeting_service_request",
            "template": "/iot/v1/meeting/service/request/{room_id}/",
            "label": "会议服务请求",
            "params": ["room_id"],
            "param_labels": {"room_id": "会议室编号"},
            "param_defaults": {"room_id": "A101"},
            "direction": "subscribe",
        },
    ],
    "central": [
        # ========== 会议室在线（发布主题不同）==========
        {
            "key": "room_online",
            "template_subscribe": "/maintain/room/master/{room_id}/",
            "template_publish": "/maintain/room/online/{room_id}/",
            "label": "会议室在线",
            "device_type": "room_online",
            "params": ["room_id"],
            "param_labels": {"room_id": "会议室编号"},
            "param_defaults": {"room_id": "A101"},
        },
        # ========== 设备在线 ==========
        {
            "key": "device_online",
            "template_subscribe": "/maintain/room/master/{room_id}/",
            "template_publish": "/maintain/room/master/client/",
            "label": "设备在线",
            "device_type": "device_online",
            "params": ["room_id"],
            "param_labels": {"room_id": "会议室编号"},
            "param_defaults": {"room_id": "A101"},
        },
        # ========== 音频系统 ==========
        {
            "key": "audio",
            "template_subscribe": "/maintain/room/master/{room_id}/",
            "template_publish": "/maintain/room/master/client/",
            "label": "音频系统",
            "device_type": "audio",
            "params": ["room_id"],
            "param_labels": {"room_id": "会议室编号"},
            "param_defaults": {"room_id": "A101"},
        },
        # ========== 视频系统 ==========
        {
            "key": "video",
            "template_subscribe": "/maintain/room/master/{room_id}/",
            "template_publish": "/maintain/room/master/client/",
            "label": "视频系统",
            "device_type": "video",
            "params": ["room_id"],
            "param_labels": {"room_id": "会议室编号"},
            "param_defaults": {"room_id": "A101"},
        },
        # ========== 控制系统 ==========
        {
            "key": "control",
            "template_subscribe": "/maintain/room/master/{room_id}/",
            "template_publish": "/maintain/room/master/client/",
            "label": "控制系统",
            "device_type": "control",
            "params": ["room_id"],
            "param_labels": {"room_id": "会议室编号"},
            "param_defaults": {"room_id": "A101"},
        },
        # ========== 网络系统 ==========
        {
            "key": "network",
            "template_subscribe": "/maintain/room/master/{room_id}/",
            "template_publish": "/maintain/room/master/client/",
            "label": "网络系统",
            "device_type": "network",
            "params": ["room_id"],
            "param_labels": {"room_id": "会议室编号"},
            "param_defaults": {"room_id": "A101"},
        },
        # ========== 电源系统 ==========
        {
            "key": "power",
            "template_subscribe": "/maintain/room/master/{room_id}/",
            "template_publish": "/maintain/room/master/client/",
            "label": "电源系统",
            "device_type": "power",
            "params": ["room_id"],
            "param_labels": {"room_id": "会议室编号"},
            "param_defaults": {"room_id": "A101"},
        },
    ],
    "client": [],    # 暂无真实主题，保留旧格式
}


def get_topic_templates(device_type: str) -> List[dict]:
    """
    获取指定设备类型的主题模板列表

    Args:
        device_type: 设备类型 (door/paperless/central/client)

    Returns:
        List[dict]: 主题模板列表
    """
    return DEVICE_TOPIC_TEMPLATES.get(device_type, [])


def has_real_topics(device_type: str) -> bool:
    """
    判断设备类型是否有真实主题模板

    Args:
        device_type: 设备类型

    Returns:
        bool: 是否有真实主题模板
    """
    return bool(DEVICE_TOPIC_TEMPLATES.get(device_type, []))


def resolve_topic(template: str, params: dict) -> str:
    """
    解析主题模板，用参数值替换占位符

    Args:
        template: 主题模板，如 "/meeting/conference/{room_id}/"
        params: 参数值映射，如 {"room_id": "A101"}

    Returns:
        str: 解析后的实际主题，如 "/meeting/conference/A101/"
    """
    result = template
    for key, value in params.items():
        result = result.replace(f"{{{key}}}", str(value))
    return result


def resolve_all_topics(device_type: str, topic_params: dict) -> Dict[str, dict]:
    """
    解析设备类型的所有主题模板

    Args:
        device_type: 设备类型
        topic_params: 参数值映射

    Returns:
        Dict[str, dict]: 解析后的主题映射，key 为模板 key，value 包含:
            - topic: 解析后的实际主题
            - direction: 方向
            - label: 中文标签
            - template: 原始模板
    """
    templates = get_topic_templates(device_type)
    resolved = {}
    for tmpl in templates:
        # 兼容新旧两种模板结构
        if "template" in tmpl:
            # 旧格式：单个 template + direction
            resolved[tmpl["key"]] = {
                "topic": resolve_topic(tmpl["template"], topic_params or {}),
                "direction": tmpl["direction"],
                "label": tmpl["label"],
                "template": tmpl["template"],
            }
        else:
            # 新格式：template_subscribe + template_publish（中控设备）
            # 订阅主题
            if "template_subscribe" in tmpl:
                resolved[tmpl["key"] + "_sub"] = {
                    "topic": resolve_topic(tmpl["template_subscribe"], topic_params or {}),
                    "direction": "subscribe",
                    "label": tmpl["label"],
                    "template": tmpl["template_subscribe"],
                    "device_type": tmpl.get("device_type"),
                }
            # 发布主题
            if "template_publish" in tmpl:
                resolved[tmpl["key"]] = {
                    "topic": resolve_topic(tmpl["template_publish"], topic_params or {}),
                    "direction": "publish",
                    "label": tmpl["label"],
                    "template": tmpl["template_publish"],
                    "device_type": tmpl.get("device_type"),
                }
    return resolved


def resolve_topics_by_device_type(device_type: str, topic_params: dict) -> Dict[str, dict]:
    """
    根据中控设备的 device_type 筛选对应主题模板

    用于中控设备，根据 topic_params.device_type 选择对应的主题模板。

    Args:
        device_type: 设备类型（应为 "central"）
        topic_params: 参数值映射，需包含 device_type 字段

    Returns:
        Dict[str, dict]: 解析后的主题映射
    """
    templates = get_topic_templates(device_type)
    central_device_type = topic_params.get("device_type", "device_online")
    resolved = {}

    for tmpl in templates:
        if tmpl.get("device_type") == central_device_type:
            # 找到匹配的模板
            # 订阅主题
            if "template_subscribe" in tmpl:
                resolved[tmpl["key"] + "_sub"] = {
                    "topic": resolve_topic(tmpl["template_subscribe"], topic_params or {}),
                    "direction": "subscribe",
                    "label": tmpl["label"],
                    "template": tmpl["template_subscribe"],
                    "device_type": tmpl.get("device_type"),
                }
            # 发布主题
            if "template_publish" in tmpl:
                resolved[tmpl["key"]] = {
                    "topic": resolve_topic(tmpl["template_publish"], topic_params or {}),
                    "direction": "publish",
                    "label": tmpl["label"],
                    "template": tmpl["template_publish"],
                    "device_type": tmpl.get("device_type"),
                }
            break  # 只取匹配的一种

    return resolved


def get_default_params(device_type: str) -> dict:
    """
    获取设备类型的默认参数值

    Args:
        device_type: 设备类型

    Returns:
        dict: 默认参数值映射
    """
    templates = get_topic_templates(device_type)
    defaults = {}
    for tmpl in templates:
        for param_key, default_val in tmpl.get("param_defaults", {}).items():
            if param_key not in defaults:
                defaults[param_key] = default_val
    return defaults
