package com.evobms.framework.config;

import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
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.handler.AbstractMessageHandler;
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;
import org.slf4j.MDC;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;

/**
 * MQTT配置类
 * 只有在mqtt.enabled=true时才会加载此配置
 *
 * @author evobms
 */
@Configuration
@ConditionalOnProperty(name = "mqtt.enabled", havingValue = "true")
public class MqttConfig {

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

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

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

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

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

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

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

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

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

    // 支持逗号分隔的多个主题，例如：/bbox/EVO0002/#,/bbox/000010000200003/#
    @Value("#{'${mqtt.subscribeTopic}'.split(',')}")
    private String[] subscribeTopics;

    /**
     * MQTT客户端工厂
     */
    @Bean
    public MqttPahoClientFactory mqttClientFactory() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        MqttConnectOptions options = new MqttConnectOptions();
        options.setServerURIs(new String[]{host});
        options.setAutomaticReconnect(automaticReconnect);
        options.setCleanSession(cleanSession);
        options.setConnectionTimeout(connectionTimeout);
        options.setKeepAliveInterval(keepAliveInterval);
        if (username != null && !username.isEmpty()) {
            options.setUserName(username);
        }
        if (password != null && !password.isEmpty()) {
            options.setPassword(password.toCharArray());
        }
        factory.setConnectionOptions(options);
        return factory;
    }

    /**
     * MQTT消息接收通道
     */
    @Bean
    public MessageChannel mqttInputChannel() {
        return new DirectChannel();
    }

    /**
     * MQTT消息生产者（订阅）
     */
    @Bean
    public MessageProducer inbound() {
        // 去除每个主题的首尾空格
        String[] topics = Arrays.stream(subscribeTopics)
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .toArray(String[]::new);
        log.info("MQTT订阅主题: {}", Arrays.toString(topics));

        MqttPahoMessageDrivenChannelAdapter adapter =
                new MqttPahoMessageDrivenChannelAdapter(clientId + "_inbound", mqttClientFactory(), topics);
        adapter.setCompletionTimeout(5000);
        // 使用字节载荷转换器，保留原始二进制帧
        DefaultPahoMessageConverter converter = new DefaultPahoMessageConverter();
        converter.setPayloadAsBytes(true);
        adapter.setConverter(converter);
        adapter.setQos(1);
        adapter.setOutputChannel(mqttInputChannel());
        return adapter;
    }

    @Autowired(required = false)
    private com.evobms.project.bms.service.MqttService mqttService;

    /**
     * MQTT消息处理器
     */
    @Bean
    @ServiceActivator(inputChannel = "mqttInputChannel")
    public MessageHandler handler() {
        return new AbstractMessageHandler() {
            @Override
            protected void handleMessageInternal(org.springframework.messaging.Message<?> message) {
                String topic = message.getHeaders().get("mqtt_receivedTopic").toString();
                try {
                    MDC.put("topic", topic);
                    // 将设备编号加入上下文，方便日志追踪
                    String[] parts = topic.split("/");
                    for (int i = 0; i < parts.length - 1; i++) {
                        if ("bbox".equalsIgnoreCase(parts[i])) {
                            MDC.put("deviceCode", parts[i + 1]);
                            break;
                        }
                    }

                    Object payloadObj = message.getPayload();
                    byte[] payloadBytes;
                    if (payloadObj instanceof byte[]) {
                        payloadBytes = (byte[]) payloadObj;
                    } else if (payloadObj instanceof String) {
                        // 尽最大可能保留原始字节（ISO_8859_1一一映射）
                        payloadBytes = ((String) payloadObj).getBytes(StandardCharsets.ISO_8859_1);
                    } else {
                        payloadBytes = payloadObj.toString().getBytes(StandardCharsets.ISO_8859_1);
                    }

                    if (mqttService != null) {
                        mqttService.handleDeviceData(topic, payloadBytes);
                    } else {
                        log.warn("mqttService未注入，无法处理设备数据，主题: {}", topic);
                    }
                } finally {
                    MDC.clear();
                }
            }
        };
    }

    /**
     * MQTT消息发送通道
     */
    @Bean
    public MessageChannel mqttOutboundChannel() {
        return new DirectChannel();
    }

    /**
     * MQTT消息发送处理器
     */
    @Bean
    @ServiceActivator(inputChannel = "mqttOutboundChannel")
    public MessageHandler mqttOutbound() {
        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(clientId + "_outbound", mqttClientFactory());
        messageHandler.setAsync(true);
        messageHandler.setDefaultTopic("evobms/command");
        messageHandler.setDefaultQos(1);
        return messageHandler;
    }
}
