package com.ruoyi.mqtt.service;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.mqtt.constant.MqttTopicConstants;
import com.ruoyi.mqtt.dto.MqttBaseMessage;
import com.ruoyi.mqtt.util.MqttTopicUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessageChannel;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
 * MQTT 消息发送服务（向 EMQX 下发指令到设备）
 */
@Service
public class MqttSendService {

    private static final Logger log = LoggerFactory.getLogger(MqttSendService.class);

    @Autowired
    private MessageChannel mqttOutputChannel;

    /**
     * 发送消息到 EMQX
     *
     * @param topic 消息主题
     * @param payload 消息体
     * @param qos QoS 级别（0/1/2）
     * @param retained 是否保留消息
     * @return 发送结果
     */
    public boolean sendMessage(String topic, String payload, int qos, boolean retained) {
        if (StringUtils.isEmpty(topic) || StringUtils.isEmpty(payload)) {
            log.error("MQTT 发送失败：主题或消息体为空");
            return false;
        }
        try {
            org.springframework.messaging.Message<String> message = MessageBuilder
                    .withPayload(payload)
                    .setHeader("mqtt_topic", topic)
                    .setHeader("mqtt_qos", qos)
                    .setHeader("mqtt_retained", retained)
                    .build();
            boolean result = mqttOutputChannel.send(message);
            if (result) {
                log.info("发送 MQTT 消息成功 -> 主题：{}，内容：{}", topic, payload);
            } else {
                log.error("发送 MQTT 消息失败 -> 主题：{}，内容：{}", topic, payload);
            }
            return result;
        } catch (Exception e) {
            log.error("发送 MQTT 消息异常", e);
            return false;
        }
    }

    /**
     * 简化发送（默认 QoS=1，不保留消息）
     */
    public boolean sendMessage(String topic, String payload) {
        return sendMessage(topic, payload, 1, false);
    }
    
    // ==================== LD导航系统专用方法 ====================
    
    /**
     * 发送LD导航系统消息
     * @param shortTopic 短主题名
     * @param args 消息参数
     * @param qos QoS级别
     * @param retained 是否保留
     * @return 发送结果
     */
    public boolean sendLdMessage(String shortTopic, Object args, int qos, boolean retained) {
        String fullTopic = MqttTopicUtil.buildTopic(shortTopic);
        MqttBaseMessage<Object> message = new MqttBaseMessage<>(System.currentTimeMillis(), args);
        String payload = JSON.toJSONString(message);
        return sendMessage(fullTopic, payload, qos, retained);
    }
    
    /**
     * 请求地图列表
     * @return 发送结果
     */
    public boolean requestMapList() {
        return sendLdMessage(MqttTopicConstants.MAP_SERVICE_MAPLIST_REQUEST, null, 2, false);
    }
    
    /**
     * 位姿初始化(通过坐标)
     * @param x X坐标
     * @param y Y坐标
     * @param yaw 航向角(弧度)
     * @return 发送结果
     */
    public boolean initPose(double x, double y, double yaw) {
        Object args = Collections.singletonList(
            new Object() {
                public final Object pose = new Object() {
                    public final List<Double> xyz = Arrays.asList(x, y, 0.0);
                    public final List<Double> rpy = Arrays.asList(0.0, 0.0, yaw);
                    public final Object blh = null;
                };
            }
        );
        return sendLdMessage(MqttTopicConstants.LOCALIZATION_ACTION_INIT, args, 2, false);
    }
    
    /**
     * 位姿初始化(通过路网点ID)
     * @param nidValue 路网点ID
     * @return 发送结果
     */
    public boolean initPoseByNid(int nidValue) {
        Object args = Collections.singletonList(
                new Object() {
                    public final Integer nid = Integer.valueOf(nidValue);
                }
        );
        return sendLdMessage(MqttTopicConstants.LOCALIZATION_ACTION_INIT, args, 2, false);
    }
    
    /**
     * 开启导航
     * @param mapName 地图名称
     * @return 发送结果
     */
    public boolean startNavigation(String mapName) {
        List<String> args = Collections.singletonList(mapName);
        return sendLdMessage(MqttTopicConstants.NAVIGATION_STACK_ACTION_START, args, 2, false);
    }
    
    /**
     * 关闭导航
     * @return 发送结果
     */
    public boolean stopNavigation() {
        return sendLdMessage(MqttTopicConstants.NAVIGATION_STACK_ACTION_STOP, null, 2, false);
    }
    
    /**
     * 重启导航
     * @param mapName 地图名称(可选,为null则使用当前地图)
     * @return 发送结果
     */
    public boolean restartNavigation(String mapName) {
        Object args = mapName != null ? Collections.singletonList(mapName) : null;
        return sendLdMessage(MqttTopicConstants.NAVIGATION_STACK_ACTION_RESTART, args, 2, false);
    }
    
    /**
     * 前往目标点(通过路网点ID)
     * @param mapName 地图名称
     * @param nidValue 目标点ID
     * @return 发送结果
     */
    public boolean gotoTargetByNid(String mapName, int nidValue) {
        Object args = Collections.singletonList(
            new Object() {
                public final String roadmap = mapName;
                public final List<Integer> nid = Collections.singletonList(Integer.valueOf(nidValue));
            }
        );
        return sendLdMessage(MqttTopicConstants.TASK_TARGET_ACTION_GOTO, args, 2, false);
    }
    
    /**
     * 前往目标点(通过坐标)
     * @param mapName 地图名称
     * @param x X坐标
     * @param y Y坐标
     * @return 发送结果
     */
    public boolean gotoTargetByCoord(String mapName, double x, double y) {
        Object args = Collections.singletonList(
            new Object() {
                public final String roadmap = mapName;
                public final List<List<Double>> coord = Collections.singletonList(Arrays.asList(x, y));
            }
        );
        return sendLdMessage(MqttTopicConstants.TASK_TARGET_ACTION_GOTO, args, 2, false);
    }
    
    /**
     * 暂停任务
     * @return 发送结果
     */
    public boolean pauseTask() {
        return sendLdMessage(MqttTopicConstants.TASK_PROCEDURE_ACTION_PAUSE, null, 1, false);
    }
    
    /**
     * 继续任务
     * @return 发送结果
     */
    public boolean resumeTask() {
        return sendLdMessage(MqttTopicConstants.TASK_PROCEDURE_ACTION_RESUME, null, 2, false);
    }
    
    /**
     * 取消任务
     * @return 发送结果
     */
    public boolean cancelTask() {
        return sendLdMessage(MqttTopicConstants.TASK_PROCEDURE_ACTION_CANCEL, null, 1, false);
    }
    
    /**
     * 遇障重规划
     * @return 发送结果
     */
    public boolean replan() {
        List<Integer> args = Collections.singletonList(0);
        return sendLdMessage(MqttTopicConstants.PLANNING_ACTION_REPLAN, args, 2, false);
    }

    /**
     * 请求路径规划
     * @param mapName 地图名称
     * @param x 目标X坐标
     * @param y 目标Y坐标
     * @return 发送结果
     */
    public boolean requestPlanning(String mapName, double x, double y) {
        Object args = Collections.singletonList(
            new Object() {
                public final String roadmap = mapName;
                public final List<Integer> nid = Collections.emptyList();
                public final List<List<Double>> coord = Collections.singletonList(Arrays.asList(x, y));
            }
        );
        return sendLdMessage(MqttTopicConstants.PLANNING_SERVICE_PLAN_REQUEST, args, 2, false);
    }

    /**
     * 启动任务
     * @param mapName 地图名称
     * @param taskName 任务名称
     * @return 发送结果
     */
    public boolean startTask(String mapName, String taskName) {
        Object args = Collections.singletonList(
            new Object() {
                public final String roadmap = mapName;
                public final String task = taskName;
            }
        );
        return sendLdMessage(MqttTopicConstants.TASK_PROCEDURE_ACTION_START, args, 2, false);
    }
    
    // ==================== ASM远程功能调用方法 ====================
    
    /**
     * 发送ASM远程功能调用
     * @param functionName 功能名称
     * @param argCount 参数个数
     * @param argValues 参数列表
     * @param qos QoS级别
     * @return 发送结果
     */
    public boolean sendAsmFunction(String functionName, int argCount, List<String> argValues, int qos) {
        Object args = Collections.singletonList(
            new Object() {
                public final String function = functionName;
                public final int argc = argCount;
                public final List<String> argv = argValues;
            }
        );
        return sendLdMessage(MqttTopicConstants.ABILITY_FUNCTION_ACTION_EXEC, args, qos, false);
    }
    
    /**
     * 开始录制（sensor_record）
     * @param mapName 地图名称
     * @return 发送结果
     */
    public boolean startRecord(String mapName) {
        List<String> argv = Collections.singletonList(mapName);
        return sendAsmFunction(MqttTopicConstants.ASM_SENSOR_RECORD_START, 1, argv, 2);
    }
    
    /**
     * 停止录制（sensor_record）
     * @return 发送结果
     */
    public boolean stopRecord() {
        return sendAsmFunction(MqttTopicConstants.ASM_SENSOR_RECORD_STOP, 0, Collections.emptyList(), 2);
    }
    
    /**
     * 开始构建地图（map_build）
     * @param mapName 地图名称
     * @param buildSteps 构建步骤（null表示全部，数组如["recon", "kfmix", "octomap", "tilemap", "potree"]）
     * @return 发送结果
     */
    public boolean startBuild(String mapName, List<String> buildSteps) {
        List<String> argv;
        if (buildSteps != null && !buildSteps.isEmpty()) {
            argv = new java.util.ArrayList<>();
            argv.add(mapName);
            argv.addAll(buildSteps);
        } else {
            argv = Collections.singletonList(mapName);
        }
        return sendAsmFunction(MqttTopicConstants.ASM_MAP_BUILD_START, argv.size(), argv, 2);
    }
    
    /**
     * 停止构建地图（map_build）
     * @return 发送结果
     */
    public boolean stopBuild() {
        return sendAsmFunction(MqttTopicConstants.ASM_MAP_BUILD_STOP, 0, Collections.emptyList(), 2);
    }
    
    /**
     * 开始实时建图（map_slam）
     * @param mapName 地图名称
     * @return 发送结果
     */
    public boolean startSlam(String mapName) {
        List<String> argv = Collections.singletonList(mapName);
        return sendAsmFunction(MqttTopicConstants.ASM_MAP_SLAM_START, 1, argv, 2);
    }
    
    /**
     * 停止实时建图（map_slam）
     * @return 发送结果
     */
    public boolean stopSlam() {
        return sendAsmFunction(MqttTopicConstants.ASM_MAP_SLAM_STOP, 0, Collections.emptyList(), 2);
    }
    
    /**
     * 启动标准导航（nav_standard）
     * @param mapName 地图名称
     * @return 发送结果
     */
    public boolean startNavStandard(String mapName) {
        List<String> argv = Collections.singletonList(mapName);
        return sendAsmFunction(MqttTopicConstants.ASM_NAV_STANDARD_START, 1, argv, 2);
    }
    
    /**
     * 结束标准导航（nav_standard）
     * @return 发送结果
     */
    public boolean stopNavStandard() {
        return sendAsmFunction(MqttTopicConstants.ASM_NAV_STANDARD_STOP, 0, Collections.emptyList(), 2);
    }

    // ==================== 急停控制方法 ====================

    /**
     * 车辆急停控制
     * @param stop true-急停, false-释放
     * @return 发送结果
     */
    public boolean emergencyStop(boolean stop) {
        Object args = Collections.singletonList(stop);
        return sendLdMessage(MqttTopicConstants.CONTROL_VEHICLE_ACTION_STOP, args, 2, false);
    }

    /**
     * 释放急停
     * @return 发送结果
     */
    public boolean emergencyStopRelease() {
        Object args = Collections.singletonList(false);
        return sendLdMessage(MqttTopicConstants.CONTROL_VEHICLE_ACTION_STOP, args, 2, false);
    }
}

