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

import com.alibaba.fastjson2.JSON;
import com.ruoyi.device.mqtt.handler.HandlerManager;
import com.ruoyi.device.mqtt.handler.encoder.IEncoder;
import com.ruoyi.device.mqtt.util.MsgHandlerUtil;
import com.ruoyi.device.mqtt.vo.CommonHeader;
import com.ruoyi.device.mqtt.vo.CommonTopic;
import io.netty.buffer.ByteBuf;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 报文体解析能力
 *
 * @author lwm
 */
public abstract class AbstractDecoder<T> implements IDecoder
{
    protected final Logger log = LoggerFactory.getLogger(getClass());

    @Resource
    private HandlerManager handlerManager;

    /**
     * 解码报文
     *
     * @param commonTopic topic设备信息
     * @param header 报文头
     * @param body 报文体
     * @return 解析结果
     */
    @Override
    public boolean process(CommonTopic commonTopic, CommonHeader header, ByteBuf body)
    {
        T content = decode(commonTopic, header, body);
        if (content != null)
        {
            log.info("TOPIC:{},DECODED-CONTENT:{}", commonTopic.getDeviceType() + "/" + commonTopic.getDeviceSn(),
                JSON.toJSONString(content));
            onEncoded(commonTopic, header, content);
            return true;
        }
        return false;
    }

    /**
     * 解码成功后 组帧报文下发
     */
    @SuppressWarnings("unchecked")
    protected void onEncoded(CommonTopic commonTopic, CommonHeader header, T content)
    {
        String key = MsgHandlerUtil.getEncoderKey(header.getFirstType(), header.getSecondType());
        IEncoder<T> encoder = (IEncoder<T>) handlerManager.getEncoder(key);
        if (encoder != null)
        {
            encoder.encode(content);
        }
    }

    /**
     * 金额转换：上报的单位是分，需要转换成元
     *
     * @param value 原始金额
     * @return 处理金额
     */
    public BigDecimal amountChange(Long value)
    {
        return new BigDecimal(value).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
    }

    /**
     * ByteBuf 读取length长度的byte[] 转16进制
     *
     * @param body ByteBuf
     * @param length 读取长度
     * @return 16进制字符串
     */
    protected String readHex(ByteBuf body, int length)
    {
        byte[] content = new byte[length];
        body.readBytes(content);
        return bytesToHex(content);
    }

    private String bytesToHex(byte[] bytes)
    {
        try
        {
            StringBuilder sb = new StringBuilder();
            for (byte b : bytes)
            {
                String hex = Integer.toHexString(0xFF & b);
                if (hex.length() < 2)
                {
                    sb.append('0');
                }
                sb.append(hex);
            }
            return sb.toString();
        }
        catch (Exception e)
        {
            log.error("原始数据转换为16进制错误：{}", e.getMessage(), e);
        }
        return "";
    }


    /**
     * ByteBuf 读取length长度的byte[] 转ASCII
     *
     * @param body ByteBuf
     * @param length 读取长度
     * @return ASCII字符串
     */
    protected String readASCII(ByteBuf body, int length)
    {
        byte[] content = new byte[length];
        body.readBytes(content);
        return validateASCII(content);
    }

    private String validateASCII(byte[] data)
    {
        try
        {
            StringBuilder stringBuilder = new StringBuilder();
            for (byte b : data)
            {
                if (b >= 32 && b <= 126)
                {
                    stringBuilder.append((char) b);
                }
            }
            return stringBuilder.toString();
        }
        catch (Exception e)
        {
            log.error("原始数据转换为ASCII错误：{}", e.getMessage(), e);
        }
        return "";
    }

    /**
     * 解码报文，提供扩展点
     *
     * @param commonTopic topic设备信息
     * @param header 报文头
     * @param body 报文体
     * @return 解析结果
     */
    protected abstract T decode(CommonTopic commonTopic, CommonHeader header, ByteBuf body);
}
