package com.ruoyi.device.mqtt.handler.decoder.json;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.device.mqtt.annotation.ConsumerHandler;
import com.ruoyi.device.mqtt.domain.BaseJsonBody;
import com.ruoyi.device.mqtt.enums.CmdTypeEnum;
import com.ruoyi.device.mqtt.enums.MsgTypeEnum;
import com.ruoyi.device.mqtt.handler.JsonCmdHandlerManager;
import com.ruoyi.device.mqtt.handler.decoder.AbstractDecoder;
import com.ruoyi.device.mqtt.vo.CommonHeader;
import com.ruoyi.device.mqtt.vo.CommonTopic;
import io.netty.buffer.ByteBuf;
import jakarta.annotation.Resource;

import java.nio.charset.StandardCharsets;

/**
 * 解析 firstType=0x4A 的 UTF-8 JSON Body，按 {@link CmdTypeEnum} 分发业务并控制下行。
 *
 * @author lwm
 */
@ConsumerHandler(msgType = MsgTypeEnum.JSON_BODY)
public class JsonBodyDecoder extends AbstractDecoder<BaseJsonBody>
{
    @Resource
    private JsonCmdHandlerManager jsonCmdHandlerManager;

    @Override
    protected BaseJsonBody decode(CommonTopic commonTopic, CommonHeader header, ByteBuf body)
    {
        // 1、按照 msgLength-2 的长度读取报文体
        if (header.getMsgLength() <= 2)
        {
            log.info("报文体长度标识小于2，忽略解析");
            return BaseJsonBody.fail(commonTopic.getDeviceType(), commonTopic.getDeviceSn(), "报文体长度标识小于2，忽略解析");
        }
        byte[] bodyBytes = new byte[header.getMsgLength() - 2];
        body.readBytes(bodyBytes);
        String bodyStr = new String(bodyBytes, StandardCharsets.UTF_8).trim();

        // 2、解析报文体json
        if (!JSON.isValidObject(bodyStr))
        {
            log.info("报文体json格式化出错");
            return BaseJsonBody.fail(commonTopic.getDeviceType(), commonTopic.getDeviceSn(), "报文体json格式化出错");
        }

        // 3、json格式化为对象jsonBody
        BaseJsonBody jsonBody = JSON.parseObject(bodyStr, BaseJsonBody.class);
        if (jsonBody == null || StringUtils.isEmpty(jsonBody.getCmdType()))
        {
            log.info("报文体缺少 cmdType");
            return BaseJsonBody.fail(commonTopic.getDeviceType(), commonTopic.getDeviceSn(), "报文体缺少 cmdType");
        }
        String rawCmdType = jsonBody.getCmdType().trim();
        if (CmdTypeEnum.isDownlink(rawCmdType))
        {
            log.info("收到下行 cmdType 于上行通道, cmdType={}", rawCmdType);
            return BaseJsonBody.fail(commonTopic.getDeviceType(), commonTopic.getDeviceSn(), "cmdType 不能为下行类型");
        }
        CmdTypeEnum cmd = CmdTypeEnum.resolveUplink(rawCmdType);
        if (cmd == null)
        {
            log.info("未知 cmdType={}", rawCmdType);
            return BaseJsonBody.fail(commonTopic.getDeviceType(), commonTopic.getDeviceSn(), "未知 cmdType: " + rawCmdType);
        }
        if (StringUtils.isEmpty(jsonBody.getDeviceType()) && StringUtils.isNotEmpty(commonTopic.getDeviceType()))
        {
            jsonBody.setDeviceType(commonTopic.getDeviceType());
            JSONObject jsonObject = JSON.parseObject(bodyStr);
            jsonObject.put("deviceType", commonTopic.getDeviceType());
            bodyStr = jsonObject.toJSONString();
        }
        if (jsonBody.getDeviceSn() == null && commonTopic.getDeviceSn() != null)
        {
            jsonBody.setDeviceSn(commonTopic.getDeviceSn());
            JSONObject jsonObject = JSON.parseObject(bodyStr);
            jsonObject.put("deviceSn", commonTopic.getDeviceSn());
            bodyStr = jsonObject.toJSONString();
        }

        // 4、进行业务处理
        IJsonCmdUpHandler handler = jsonCmdHandlerManager.getUpHandlerByUpKey(cmd.getCmdUpType());
        if (handler == null)
        {
            handler = jsonCmdHandlerManager.getUpHandlerByBaseKey(cmd.getCmdType());
        }
        if (handler == null)
        {
            log.info("未注册 JSON 命令处理器 cmd={}", cmd);
            return BaseJsonBody.fail(jsonBody.getDeviceType(), jsonBody.getDeviceSn(), cmd.getCmdDownType(), "未实现的服务处理器");
        }
        return handler.handle(commonTopic, header, bodyStr, cmd);
    }
}
