package com.usky.eg.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.usky.common.core.exception.BusinessException;
import com.usky.eg.mqtt.EgMqttOutboundConfig.EgMqttPublishGateway;
import com.usky.eg.mqtt.EgMqttProperties;
import com.usky.eg.service.EgDeviceRemoteUpgradeMqttService;
import com.usky.eg.service.vo.EgDeviceAdbRemoteUpgradeBatchItemVO;
import com.usky.eg.service.vo.EgDeviceAdbRemoteUpgradeBatchResultVO;
import com.usky.eg.service.vo.EgDeviceAdbRemoteUpgradeItemResultVO;
import com.usky.eg.service.vo.EgDeviceAdbRemoteUpgradeVO;
import com.usky.eg.service.vo.EgDeviceAdbResultVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class EgDeviceRemoteUpgradeMqttServiceImpl implements EgDeviceRemoteUpgradeMqttService {

    @Autowired
    private EgMqttPublishGateway mqttPublishGateway;

    @Autowired
    private EgMqttProperties mqttProperties;

    @Override
    public EgDeviceAdbResultVO publishRemoteUpgrade(EgDeviceAdbRemoteUpgradeVO vo) {
        if (vo == null) {
            return EgDeviceAdbResultVO.fail("请求体为空");
        }
        if (StringUtils.isBlank(vo.getFileUrl())) {
            throw new BusinessException("fileUrl 不能为空");
        }
        String urlTrim = vo.getFileUrl().trim();
        if (!urlTrim.startsWith("http://") && !urlTrim.startsWith("https://")) {
            throw new BusinessException("fileUrl 须为 http 或 https 地址");
        }
        String deviceId = resolveDeviceId(vo.getDeviceId(), vo.getDeviceCode());
        if (StringUtils.isBlank(deviceId)) {
            throw new BusinessException("MQTT 下发须指定 deviceId 或 deviceCode（与终端 connectWithDevice.deviceId 一致）");
        }
        String topic = buildTopic(deviceId);
        String cmdId = UUID.randomUUID().toString();
        String payload = buildPayload(cmdId, urlTrim, vo.getLaunchPackage(),
                vo.getDeviceCode(), vo.getDeviceIp(), vo.getDevicePort());
        return publishOne(topic, payload, cmdId);
    }

    @Override
    public EgDeviceAdbRemoteUpgradeBatchResultVO publishRemoteUpgradeBatch(List<EgDeviceAdbRemoteUpgradeBatchItemVO> items,
                                                                           String fileUrl, String launchPackage) {
        if (items == null || items.isEmpty()) {
            throw new BusinessException("items 不能为空");
        }
        if (StringUtils.isBlank(fileUrl)) {
            throw new BusinessException("fileUrl 不能为空");
        }
        String urlTrim = fileUrl.trim();
        if (!urlTrim.startsWith("http://") && !urlTrim.startsWith("https://")) {
            throw new BusinessException("fileUrl 须为 http 或 https 地址");
        }
        List<EgDeviceAdbRemoteUpgradeItemResultVO> rows = new ArrayList<>(items.size());
        int success = 0;
        int fail = 0;
        int index = 0;
        for (EgDeviceAdbRemoteUpgradeBatchItemVO item : items) {
            EgDeviceAdbResultVO r;
            String mqttTopic = null;
            String mqttCmdId = null;
            if (item == null) {
                r = EgDeviceAdbResultVO.fail("请求项为空");
            } else {
                String deviceId = resolveDeviceId(item.getDeviceId(), item.getDeviceCode());
                if (StringUtils.isBlank(deviceId)) {
                    r = EgDeviceAdbResultVO.fail("须指定 deviceId 或 deviceCode");
                } else {
                    try {
                        String topic = buildTopic(deviceId);
                        String cmdId = UUID.randomUUID().toString();
                        String payload = buildPayload(cmdId, urlTrim, launchPackage,
                                item.getDeviceCode(), item.getDeviceIp(), item.getDevicePort());
                        r = publishOne(topic, payload, cmdId);
                        mqttTopic = topic;
                        mqttCmdId = cmdId;
                    } catch (BusinessException e) {
                        r = EgDeviceAdbResultVO.fail(e.getMessage() != null ? e.getMessage() : "参数错误");
                    } catch (Exception e) {
                        log.warn("mqtt remote upgrade publish failed index={} deviceId={}", index, deviceId, e);
                        r = EgDeviceAdbResultVO.fail(e.getMessage() != null ? e.getMessage() : e.toString());
                    }
                }
            }
            if (EgDeviceAdbResultVO.STATUS_SUCCESS.equals(r.getStatus())) {
                success++;
            } else {
                fail++;
            }
            String code = item != null ? item.getDeviceCode() : null;
            String ip = item != null ? item.getDeviceIp() : null;
            String port = item != null ? item.getDevicePort() : null;
            String routeId = item != null ? resolveDeviceId(item.getDeviceId(), item.getDeviceCode()) : null;
            rows.add(new EgDeviceAdbRemoteUpgradeItemResultVO(index++, code, ip, port, routeId, mqttTopic, mqttCmdId, r));
        }
        return new EgDeviceAdbRemoteUpgradeBatchResultVO(items.size(), success, fail, rows);
    }

    private EgDeviceAdbResultVO publishOne(String topic, String payload, String cmdId) {
        try {
            int qos = clampQos(mqttProperties.getQos());
            mqttPublishGateway.sendToMqtt(topic, qos, payload);
            log.info("mqtt remote upgrade published topic={} cmdId={}", topic, cmdId);
            return EgDeviceAdbResultVO.ok("topic=" + topic + "; cmdId=" + cmdId);
        } catch (Exception e) {
            log.warn("mqtt publish failed topic={} cmdId={}", topic, cmdId, e);
            return EgDeviceAdbResultVO.fail(e.getMessage() != null ? e.getMessage() : e.toString());
        }
    }

    private String buildPayload(String cmdId, String fileUrl, String launchPackage,
                                String deviceCode, String deviceIp, String devicePort) {
        JSONObject o = new JSONObject();
        o.put("id", cmdId);
        o.put("type", mqttProperties.getCommandType() != null ? mqttProperties.getCommandType() : "egRemoteUpgrade");
        o.put("fileUrl", fileUrl.trim());
        if (StringUtils.isNotBlank(launchPackage)) {
            o.put("launchPackage", launchPackage.trim());
        }
        if (StringUtils.isNotBlank(deviceCode)) {
            o.put("deviceCode", deviceCode.trim());
        }
        if (StringUtils.isNotBlank(deviceIp)) {
            o.put("deviceIp", deviceIp.trim());
        }
        if (StringUtils.isNotBlank(devicePort)) {
            o.put("devicePort", devicePort.trim());
        }
        return o.toJSONString();
    }

    private static String resolveDeviceId(String deviceId, String deviceCode) {
        if (StringUtils.isNotBlank(deviceId)) {
            return deviceId.trim();
        }
        if (StringUtils.isNotBlank(deviceCode)) {
            return deviceCode.trim();
        }
        return null;
    }

    private String buildTopic(String deviceId) {
        String template = mqttProperties.getCommandTopicTemplate();
        if (StringUtils.isBlank(template) || !template.contains("{deviceId}")) {
            throw new BusinessException("eg.mqtt.command-topic-template 须为非空且包含占位符 {deviceId}");
        }
        return template.replace("{deviceId}", deviceId);
    }

    private static int clampQos(int qos) {
        if (qos < 0) {
            return 0;
        }
        if (qos > 2) {
            return 2;
        }
        return qos;
    }
}
