package com.evobms.project.bms.controller;

import com.evobms.framework.web.domain.AjaxResult;
import com.evobms.common.constant.Constants;
import com.evobms.common.constant.BboxApiConstants;
import com.evobms.common.utils.StringUtils;
import com.evobms.project.bms.service.MqttService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * MQTT消息发布控制器
 * 用于测试MQTT消息的发布和接收
 *
 * @author ruoyi
 * @date 2024-01-01
 */
@RestController
@RequestMapping("/bms/mqtt")
@Api(tags = "MQTT消息发布")
public class MqttPublishController  {
    private static final Logger log = LoggerFactory.getLogger(MqttPublishController.class);

    @Autowired(required = false)
    private MqttService mqttService;

    @Value("${token.header}")
    private String tokenHeader;

    /**
     * 发布测试消息到指定主题
     */
    @PostMapping("/publish")
   // @Log(title = "MQTT消息发布", businessType = BusinessType.INSERT)
    @ApiOperation("发布文本消息")
    public AjaxResult publishMessage(@RequestParam String topic, @RequestParam String message) {
        try {
            if (mqttService == null) {
                return AjaxResult.error("MQTT服务未启用");
            }
            mqttService.sendMessage(topic, message);
            log.info("发布消息成功 -> 主题: {}, 内容: {}", topic, message);
            return AjaxResult.success("消息发布成功", "主题: " + topic + ", 内容: " + message);
        } catch (Exception e) {
            log.error("发布消息失败 -> 主题: {}, 错误: {}", topic, e.getMessage(), e);
            return AjaxResult.error("消息发布失败: " + e.getMessage());
        }
    }

    /**
     * 发布原始十六进制字节消息到指定主题
     */
    @PostMapping("/publishHex")
    @ApiOperation("发布HEX消息")
    public AjaxResult publishHex(@RequestParam String topic, @RequestParam String hex) {
        try {
            if (mqttService == null) {
                return AjaxResult.error("MQTT服务未启用");
            }

            byte[] payload = parseHexToBytes(hex);
            mqttService.sendMessageBytes(topic, payload);
            log.info("发布HEX消息成功 -> 主题: {}, 长度: {}, HEX: {}", topic, payload.length, toHex(payload));
            return AjaxResult.success("HEX消息发布成功", "主题: " + topic + ", 字节长度: " + payload.length);
        } catch (Exception e) {
            log.error("发布HEX消息失败 -> 主题: {}, 错误: {}", topic, e.getMessage(), e);
            return AjaxResult.error("HEX消息发布失败: " + e.getMessage());
        }
    }

    /**
     * 获取当前请求的鉴权令牌（从请求头读取并去除前缀）
     */
    @GetMapping("/authToken")
    @ApiOperation("获取鉴权令牌")
    public AjaxResult getAuthToken(HttpServletRequest request) {
        try {
            String raw = request.getHeader(tokenHeader);
            String token = raw;
            if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) {
                token = token.replace(Constants.TOKEN_PREFIX, "");
            }
            if (StringUtils.isEmpty(token)) {
                return AjaxResult.error(BboxApiConstants.CODE_UNAUTHORIZED, BboxApiConstants.MSG_UNAUTHORIZED + "：未检测到令牌，请登录或在请求头设置 " + tokenHeader);
            }
            AjaxResult ajax = AjaxResult.success();
            ajax.put(Constants.TOKEN, token);
            ajax.put("header", tokenHeader);
            return ajax;
        } catch (Exception e) {
            log.error("获取鉴权令牌失败: {}", e.getMessage(), e);
            return AjaxResult.error("获取鉴权令牌失败: " + e.getMessage());
        }
    }

    private static byte[] parseHexToBytes(String hex) {
        String s = hex.replace("0x", "").replace("0X", "").replaceAll("\\s+", "");
        if (s.length() == 0) {
            throw new IllegalArgumentException("HEX字符串为空");
        }
        if (s.length() % 2 != 0) {
            throw new IllegalArgumentException("HEX长度必须为偶数");
        }
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            String byteStr = s.substring(i, i + 2);
            int val = Integer.parseInt(byteStr, 16);
            data[i / 2] = (byte) val;
        }
        return data;
    }

    private static String toHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString().trim();
    }

    /**
     * 发布设备数据测试消息
     */
    @PostMapping("/publishDeviceData")
   // @Log(title = "设备数据发布", businessType = BusinessType.INSERT)
    @ApiOperation("发布设备测试数据")
    public AjaxResult publishDeviceData(@RequestParam String deviceCode) {
        try {
            if (mqttService == null) {
                return AjaxResult.error("MQTT服务未启用");
            }

            // 构造测试数据
            String testData = "{"
                + "\"voltage\": 12.5,"
                + "\"current\": 2.3,"
                + "\"capacity\": 85.6,"
                + "\"temperature\": 25.8,"
                + "\"timestamp\": " + System.currentTimeMillis()
                + "}";

            String topic = "evobms/" + deviceCode + "/data";
            mqttService.sendMessage(topic, testData);
            log.info("设备数据发布成功 -> 设备: {}, 主题: {}", deviceCode, topic);

            return AjaxResult.success("设备数据发布成功",
                "主题: " + topic + ", 数据: " + testData);
        } catch (Exception e) {
            log.error("设备数据发布失败 -> 设备: {}, 错误: {}", deviceCode, e.getMessage(), e);
            return AjaxResult.error("设备数据发布失败: " + e.getMessage());
        }
    }

    /**
     * 快速测试 - 发布消息到test设备
     */
    @GetMapping("/quickTest")
    @ApiOperation("快速测试发布")
    public AjaxResult quickTest() {
        try {
            if (mqttService == null) {
                return AjaxResult.error("MQTT服务未启用");
            }

            // 发布到test设备
            String topic = "evobms/test/data";
            String testData = "{"
                + "\"voltage\": 13.2,"
                + "\"current\": 1.8,"
                + "\"capacity\": 92.3,"
                + "\"temperature\": 23.5,"
                + "\"timestamp\": " + System.currentTimeMillis()
                + "}";

            mqttService.sendMessage(topic, testData);
            log.info("快速测试消息已发布 -> 主题: {}", topic);

            return AjaxResult.success("快速测试完成",
                "已发布消息到主题: " + topic + ", 请查看控制台日志");
        } catch (Exception e) {
            log.error("快速测试失败 -> 错误: {}", e.getMessage(), e);
            return AjaxResult.error("快速测试失败: " + e.getMessage());
        }
    }

    /**
     * 批量发布测试消息
     */
    @PostMapping("/batchPublish")
   // @Log(title = "批量MQTT消息发布", businessType = BusinessType.INSERT)
    @ApiOperation("批量发布测试消息")
    public AjaxResult batchPublish(@RequestParam String deviceCode, @RequestParam(defaultValue = "5") int count) {
        try {
            if (mqttService == null) {
                return AjaxResult.error("MQTT服务未启用");
            }

            String topic = "evobms/" + deviceCode + "/data";

            for (int i = 0; i < count; i++) {
                String testData = "{"
                    + "\"voltage\": " + (12.0 + Math.random() * 2) + ","
                    + "\"current\": " + (1.0 + Math.random() * 3) + ","
                    + "\"capacity\": " + (80 + Math.random() * 20) + ","
                    + "\"temperature\": " + (20 + Math.random() * 10) + ","
                    + "\"timestamp\": " + System.currentTimeMillis()
                    + "}";

                mqttService.sendMessage(topic, testData);
                log.debug("批量发布第{}条 -> 主题: {}", i + 1, topic);

                // 间隔100ms
                Thread.sleep(100);
            }

            return AjaxResult.success("批量发布完成",
                "已发布 " + count + " 条消息到主题: " + topic);
        } catch (Exception e) {
            log.error("批量发布失败 -> 设备: {}, 错误: {}", deviceCode, e.getMessage(), e);
            return AjaxResult.error("批量发布失败: " + e.getMessage());
        }
    }
}
