package com.ruoyi.mqtt.config;

import com.ruoyi.mqtt.listener.MqttMessageListener;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;

/**
 * EMQX MQTT 配置类
 * 配置参数从 application.yml 中读取
 */
@Configuration
public class MqttConfig {

    @Value("${mqtt.broker:tcp://192.168.0.30:1883}")
    private String broker;

    @Value("${mqtt.username:gbd01}")
    private String username;

    @Value("${mqtt.password:gbd2025!}")
    private String password;

    @Value("${mqtt.clientId:mqttx_1e1f7a7e}")
    private String clientId;

    @Value("${mqtt.subscribeTopics:}")
    private String subscribeTopics;

    @Value("${mqtt.deviceId:}")
    private String deviceId;

    @Value("${mqtt.qos:1}")
    private int qos;

    @Value("${mqtt.keepAliveInterval:60}")
    private int keepAliveInterval;

    @Value("${mqtt.connectionTimeout:30}")
    private int connectionTimeout;

    @Value("${mqtt.automaticReconnect:true}")
    private boolean automaticReconnect;

    @Value("${mqtt.cleanSession:false}")
    private boolean cleanSession;

    @Value("${mqtt.productId:robot4inspection}")
    private String productId;

    public String getProductId() {
        return productId;
    }

    public String getDeviceId() {
        return deviceId;
    }

    @Bean
    public MqttConnectOptions mqttConnectOptions() {
        MqttConnectOptions options = new MqttConnectOptions();
        options.setServerURIs(new String[]{broker});
        options.setUserName(username);
        options.setPassword(password.toCharArray());
        options.setAutomaticReconnect(automaticReconnect);
        options.setKeepAliveInterval(keepAliveInterval);
        options.setConnectionTimeout(connectionTimeout);
        options.setCleanSession(cleanSession);
        return options;
    }

    @Bean
    public MqttPahoClientFactory mqttClientFactory() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        factory.setConnectionOptions(mqttConnectOptions());
        return factory;
    }

    @Bean
    public MessageChannel mqttInputChannel() {
        return new DirectChannel();
    }

    @Bean
    public MessageProducer inbound() {
        String[] topics;
        
        // 如果配置了具体的订阅主题,使用配置的主题
        if (subscribeTopics != null && !subscribeTopics.trim().isEmpty()) {
            topics = subscribeTopics.split(",");
        } else {
            // 否则使用LD导航系统的默认订阅主题
            // 必须配置deviceId才能订阅
            if (deviceId == null || deviceId.trim().isEmpty()) {
                throw new IllegalArgumentException("mqtt.deviceId 配置不能为空！请在 application.yml 中配置 mqtt.deviceId");
            }
            topics = buildDefaultSubscribeTopics();
        }
        
        MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(
                clientId + "-inbound", mqttClientFactory(), topics);
        adapter.setConverter(new DefaultPahoMessageConverter());
        adapter.setQos(qos);
        adapter.setOutputChannel(mqttInputChannel());
        return adapter;
    }
    
    /**
     * 构建默认订阅主题列表
     * 订阅指定设备的响应和事件消息
     * 主题格式: /${ProductID}/${DeviceID}/${ShortTopic}
     */
    private String[] buildDefaultSubscribeTopics() {
        // 构建主题前缀: /${ProductID}/${DeviceID}
        String prefix = "/" + productId + "/" + deviceId;
        return new String[]{
            // 地图相关
            prefix + "/map/service/maplist/response",
            prefix + "/map/property/current_map",
            
            // 定位相关
            prefix + "/localization/pose",
            prefix + "/localization/action/init/reply",
            
            // 导航相关
            prefix + "/navigation/stack/action/start/reply",
            prefix + "/navigation/stack/action/stop/reply",
            prefix + "/navigation/stack/action/restart/reply",
            
            // 规划相关
            prefix + "/planning/service/plan/response",
            prefix + "/planning/trajectory",
            prefix + "/planning/trajectory/2d/compact",
            prefix + "/planning/action/replan/reply",
            
            // 任务相关
            prefix + "/task/target/action/goto/reply",
            prefix + "/task/target/event/arrive",
            prefix + "/task/realtime/info",
            prefix + "/task/procedure/action/pause/reply",
            prefix + "/task/procedure/action/resume/reply",
            prefix + "/task/procedure/action/cancel/reply",
            
            // ASM远程功能调用相关
            prefix + "/ability/function/action/exec/reply",
            prefix + "/ability/function/action/exec/progress",
            prefix + "/ability/function/action/exec/state",

            // 传感器相关（电池信息）
            prefix + "/sensor/battery"
        };
    }

    @Bean
    @ServiceActivator(inputChannel = "mqttInputChannel")
    public MessageHandler mqttMessageHandler() {
        return new MqttMessageListener();
    }

    @Bean
    public MessageChannel mqttOutputChannel() {
        return new DirectChannel();
    }

    @Bean
    @ServiceActivator(inputChannel = "mqttOutputChannel")
    public MessageHandler mqttOutbound() {
        MqttPahoMessageHandler handler = new MqttPahoMessageHandler(
                clientId + "-outbound", mqttClientFactory());
        handler.setDefaultQos(qos);
        handler.setAsync(true);
        handler.setDefaultRetained(false);
        return handler;
    }
}
