package com.inspect.metadata.mqtt;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.inspect.metadata.mqtt.domain.*;
import com.inspect.metadata.mqtt.enums.HrDeviceEnum;
import com.inspect.metadata.mqtt.service.IHrDroneBatteryService;
import com.inspect.metadata.mqtt.service.IHrTaskProcessService;
import com.inspect.metadata.mqtt.service.IHrWarnService;
import com.inspect.metadata.mqtt.utils.HrMqttBatchProcessingService;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Service
@ConditionalOnProperty(name = {"hua-ruan.mqtt.enable"}, havingValue = "true")
public class HuaRuanMQTTServiceImpl {

    private final MQTTUtils mqttUtils;

    @Autowired
    private IHrTaskProcessService taskProcessService;

    @Autowired
    private IHrWarnService warnService;

    @Autowired
    private IHrDroneBatteryService droneBatteryService;

    @Autowired
    private HrMqttBatchProcessingService batchProcessingService;

    @Autowired
    public HuaRuanMQTTServiceImpl(MQTTUtils mqttUtils) {
        this.mqttUtils = mqttUtils;

        // 设置 MQTT 回调
        setupMqttCallback();
    }

    private void setupMqttCallback() {
        mqttUtils.getClient().setCallback(new MqttCallback() {
            @Override
            public void connectionLost(Throwable cause) {
                log.info("Connection lost: {}", cause.getMessage());
            }

            @Override
            public void messageArrived(String topic, MqttMessage message) {
                log.debug("Message arrived from topic {}: {}", topic, new String(message.getPayload()));
                handleIncomingMessage(topic, message);
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {
                log.debug("Delivery complete for message with token: {}", token.getMessageId());
            }
        });
    }

    private void handleIncomingMessage(String topic, MqttMessage message) {
        try {
            String nestCode = getNestCode(topic);
            if (nestCode.isEmpty()) {
                throw new Exception("nestCode is null");
            }
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            String jsonStr = new String(message.getPayload());
            // 机巢基础状态
            if (topic.endsWith("/thing/property/nest")) {
                log.debug("机巢基础状态: {}", nestCode);
                HrNest hrNest = objectMapper.readValue(jsonStr, HrNest.class);
                hrNest.setNestCode(nestCode);
                batchProcessingService.addNest(hrNest);
            }
            // 机巢电池状态
            else if (topic.endsWith("/thing/property/nest_battery")) {
                log.debug("机巢电池状态: {}", nestCode);
            }
            // 航站状态告警
            else if (topic.endsWith("thing/service/nest/warn")) {
                log.debug("航站状态告警: {}", nestCode);
                List<HrNestWarn> nestWarnList = objectMapper.readValue(jsonStr, new TypeReference<List<HrNestWarn>>() {
                });
                for (HrNestWarn nestWarn : nestWarnList) {
                    HrWarn warn = new HrWarn();
                    warn.setNestCode(nestCode);
                    warn.setType(HrDeviceEnum.Nest.getCode());
                    warn.setErrCode(nestWarn.getErrCode());
                    warn.setErrMsg(nestWarn.getErrMsg());
                    warn.setErrGrade(nestWarn.getErrGrade());
                    warnService.handleWarn(warn);
                }
            }
            // 无人机基础信息
            else if (topic.endsWith("/thing/property/drone")) {
                log.debug("无人机基础信息: {}", nestCode);
            }
            // 无机人电池状态
            else if (topic.endsWith("/thing/property/drone_battery")) {
                log.debug("无人机电池状态: {}", nestCode);
                HrDroneBattery droneBattery = objectMapper.readValue(jsonStr, HrDroneBattery.class);
                droneBattery.setNestCode(nestCode);
                droneBatteryService.insertDroneBattery(droneBattery);
            }
            // 无人机告警信息
            else if (topic.endsWith("/thing/property/errmsg")) {
                log.debug("无人机告警信息: {}", nestCode);
                HrDroneWarn droneWarn = objectMapper.readValue(jsonStr, HrDroneWarn.class);
                HrWarn warn = new HrWarn();
                warn.setNestCode(nestCode);
                warn.setType(droneWarn.getErrType());
                warn.setErrCode(droneWarn.getErrCode());
                warn.setErrMsg(droneWarn.getErrMsg());
                warn.setErrGrade(droneWarn.getErrRank());
                warnService.handleWarn(warn);
            }
            // 巡检任务执行过程
            else if (topic.endsWith("/thing/property/task_process")) {
                log.debug("巡检任务执行过程: {}", nestCode);
                JSONObject jsonObject = JSONObject.parseObject(jsonStr);
                HrTaskProcess taskProcess = new HrTaskProcess();
                taskProcess.setNestCode(nestCode);
                taskProcess.setPatrolTaskCode(jsonObject.getString("patrolTaskCode"));
                taskProcess.setState(jsonObject.getInteger("state"));
                JSONObject params = jsonObject.getJSONObject("param");
                taskProcess.setContent(params.getString("Content"));
                taskProcess.setStepid(params.getInteger("stepid"));
                taskProcess.setResult(params.getInteger("result"));
                taskProcess.setTime(params.getString("Time"));
                taskProcessService.insertTaskProcess(taskProcess);
            }
        } catch (Exception e) {
            log.error("MQTT handle error, topic: {}", topic, e);
        }
    }

    private final static Pattern pattern = Pattern.compile("/sys/([^/]+)/.*");

    public String getNestCode(String topic) {
        Matcher matcher = pattern.matcher(topic);

        if (matcher.find()) {
            return matcher.group(1);
        }

        return "";
    }
}
