package com.zbf.web.mqtt;

import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;

import javax.annotation.PreDestroy;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Configuration
public class MqttConfig {

    @Autowired
    private MqttProperties mqttProperties;

    @Autowired
    private MqttMessageHandler mqttMessageHandler;

    private MqttClient mqttClient;
    private volatile boolean isConnecting = false;
    private final AtomicInteger reconnectAttempts = new AtomicInteger(0);
    private static final int MAX_RECONNECT_ATTEMPTS = 5;
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

/*
    @EventListener(ApplicationReadyEvent.class)
*/
    public void onApplicationReady() {
        log.info("应用程序启动完成，准备连接MQTT...");
        scheduler.schedule(this::connect, 5, TimeUnit.SECONDS);
    }

    private synchronized void connect() {
        try {
            if (mqttClient != null && mqttClient.isConnected()) {
                log.info("MQTT客户端已连接，无需重新连接");
                return;
            }

            if (isConnecting) {
                log.info("MQTT客户端正在连接中，请稍候...");
                return;
            }

            isConnecting = true;

            if (mqttClient == null) {
                MemoryPersistence persistence = new MemoryPersistence();
                mqttClient = new MqttClient(
                        mqttProperties.getHostUrl(),
                        mqttProperties.getClientId() + "_" + System.currentTimeMillis(),
                        persistence
                );
            }

            setupMqttCallback();
            MqttConnectOptions options = createConnectOptions();

            log.info("正在连接到MQTT服务器: {}", mqttProperties.getHostUrl());
            mqttClient.connect(options);
            log.info("MQTT连接成功");
            reconnectAttempts.set(0);

            subscribeToTopics();

        } catch (MqttException e) {
            log.error("MQTT连接失败: {}", e.getMessage(), e);
            handleReconnect();
        } finally {
            isConnecting = false;
        }
    }

    private void setupMqttCallback() {
        mqttClient.setCallback(new MqttCallback() {
            @Override
            public void connectionLost(Throwable cause) {
                log.error("MQTT连接丢失: {}", cause.getMessage(), cause);
                reconnectAttempts.set(0);
                handleReconnect();
            }

            @Override
            public void messageArrived(String topic, MqttMessage message) {
                try {
                    log.info("收到消息 -> Topic: {}, QoS: {}, Message: {}",
                            topic,
                            message.getQos(),
                            new String(message.getPayload()));
                    mqttMessageHandler.handleMessage(topic, new String(message.getPayload()));
                } catch (Exception e) {
                    log.error("处理消息时发生错误: {}", e.getMessage(), e);
                }
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {
                // 不需要实现
            }
        });
    }

    private MqttConnectOptions createConnectOptions() {
        MqttConnectOptions options = new MqttConnectOptions();
        options.setUserName(mqttProperties.getUsername());
        options.setPassword(mqttProperties.getPassword().toCharArray());
        options.setConnectionTimeout(mqttProperties.getTimeout());
        options.setKeepAliveInterval(mqttProperties.getKeepalive());
        options.setAutomaticReconnect(false);
        options.setCleanSession(true);
        return options;
    }

    private void subscribeToTopics() throws MqttException {
        if (mqttProperties.getTopics() != null) {
            for (String topic : mqttProperties.getTopics()) {
                mqttClient.subscribe(topic, mqttProperties.getQos());
                log.info("已订阅主题: {}, QoS: {}", topic, mqttProperties.getQos());
            }
        }
    }

    private void handleReconnect() {
        if (reconnectAttempts.incrementAndGet() > MAX_RECONNECT_ATTEMPTS) {
            log.error("MQTT重连次数超过最大限制 ({})，停止重连", MAX_RECONNECT_ATTEMPTS);
            return;
        }

        long delay = Math.min(30, reconnectAttempts.get() * 5);
        log.info("等待{}秒后进行第 {} 次重连...", delay, reconnectAttempts.get());
        scheduler.schedule(this::connect, delay, TimeUnit.SECONDS);
    }


    public void sendMessage(String topic, String payload, int qos) {
        try {
            if (mqttClient != null && mqttClient.isConnected()) {
                MqttMessage message = new MqttMessage(payload.getBytes());
                message.setQos(qos);
                mqttClient.publish(topic, message);
                log.info("消息已发送到主题 {}: {}", topic, payload);
            } else {
                log.error("MQTT客户端未连接，无法发送消息");
                handleReconnect();
            }
        } catch (MqttException e) {
            log.error("发送消息失败: {}", e.getMessage(), e);
        }
    }

    @PreDestroy
    public void disconnect() {
        try {
            if (mqttClient != null && mqttClient.isConnected()) {
                mqttClient.disconnect();
                log.info("MQTT连接已断开");
            }
        } catch (MqttException e) {
            log.error("断开MQTT连接时发生错误: {}", e.getMessage(), e);
        } finally {
            scheduler.shutdownNow();
        }
    }
}