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

import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.device.config.DecryptDeviceConfig;
import com.ruoyi.device.mqtt.annotation.ConsumerHandler;
import com.ruoyi.device.mqtt.api.constants.ApiPathConstants;
import com.ruoyi.device.mqtt.domain.decoder.tax.TaxMonthDataMessage;
import com.ruoyi.device.mqtt.domain.decoder.tax.TaxTransferDataMessage;
import com.ruoyi.device.mqtt.domain.encoder.tax.CiphertextDataDown;
import com.ruoyi.device.mqtt.enums.DeviceModelEnum;
import com.ruoyi.device.mqtt.enums.DeviceRedisEnum;
import com.ruoyi.device.mqtt.enums.MsgTypeEnum;
import com.ruoyi.device.mqtt.enums.VersionEnum;
import com.ruoyi.device.mqtt.handler.HandlerManager;
import com.ruoyi.device.mqtt.handler.decoder.AbstractDecoder;
import com.ruoyi.device.mqtt.handler.decoder.MessageHandler;
import com.ruoyi.device.mqtt.handler.encoder.IEncoder;
import com.ruoyi.device.mqtt.util.MsgHandlerUtil;
import com.ruoyi.device.mqtt.util.TargetTypeConvertUtil;
import com.ruoyi.device.mqtt.vo.CiphertextData;
import com.ruoyi.device.mqtt.vo.CommonHeader;
import com.ruoyi.device.mqtt.vo.CommonTopic;
import com.ruoyi.device.service.ITaxTransferDataService;
import io.netty.buffer.ByteBuf;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.TimeUnit;

/**
 * 报税口密文 解密结果上行解码
 */
@ConsumerHandler(msgType = MsgTypeEnum.CIPHERTEXT_DATA_DECRYPT_UP)
public class CiphertextDataDecryptDecoder extends AbstractDecoder<Void>
{
    @Resource
    private HandlerManager handlerManager;

    @Resource
    private DecryptDeviceConfig decryptDeviceConfig;

    @Resource
    private RedisCache redisCache;

    @Resource
    private ITaxTransferDataService taxTransferDataService;

    @Override
    protected Void decode(CommonTopic commonTopic, CommonHeader header, ByteBuf body)
    {
        ByteBuf copyBuf = body.copy();
        Long gatewayNo = null;
        Long collectorNo = null;
        if (header.getProtoVer() == VersionEnum.THIRD.getValue())
        {
            TargetTypeConvertUtil.convert(body.readUnsignedShortLE());
            gatewayNo = body.readUnsignedIntLE();
            TargetTypeConvertUtil.convert(body.readUnsignedShortLE());
            collectorNo = body.readUnsignedIntLE();
        }
        else
        {
            gatewayNo = body.readUnsignedIntLE();
            collectorNo = body.readUnsignedIntLE();
        }

        int taxNo = body.readByte();
        int gunNo = body.readByte();
        Long serialNo = body.readUnsignedIntLE();
        // 环境 0：解码数据返回结服务器  1：解码数据返回给数据源设备
        int env = body.readByte();
        // 剩余空间
        int freeSpace = body.readByte();
        // 1：解码成功；2：解码超时；3：报税口数据错误；4：子板没有空闲的sim卡；5：解码失败；6：子板超时；7：主板缓存已满
        int result = body.readByte();

        String key2 = String.format(ApiPathConstants.FOUR_UNDER_LINE, gatewayNo, collectorNo, taxNo, gunNo, serialNo);
        redisCache.setCacheObject(
            String.format(DeviceRedisEnum.DEVICE_FREE_SPACE.getKey(), commonTopic.getDeviceSn()), freeSpace);

        if (result == 1 && env == 9)
        {
            CiphertextData ciphertextData = redisCache.getCacheMapValue(DeviceRedisEnum.TAX_CIPHERTEXT_DATA_SEND.getKey(), key2);
            // 偷传返回
            BigDecimal hand = new BigDecimal("100");
            body.readBytes(19);
            // 开始解析数据 累计值
            body.readBytes(7);
            String totalVolume = readASCII(body, 12);
            String totalAmount = readASCII(body, 12);

            redisCache.deleteCacheMapValue(DeviceRedisEnum.TAX_CIPHERTEXT_DATA_SEND.getKey(), key2);
            if (StringUtils.isNotBlank(ciphertextData.getPlatform()))
            {
                TaxTransferDataMessage taxTransferDataMessage = new TaxTransferDataMessage();
                taxTransferDataMessage.setGatewayNo(gatewayNo);
                taxTransferDataMessage.setCollectorNo(collectorNo);
                taxTransferDataMessage.setTaxNo(taxNo);
                taxTransferDataMessage.setGunNo(gunNo);
                taxTransferDataMessage.setSerialNo(serialNo);
                taxTransferDataMessage.setRaiseTime(ciphertextData.getRaiseTime());
                taxTransferDataMessage.setHangTime(ciphertextData.getHangTime());
                taxTransferDataMessage.setTotalVolume(new BigDecimal(totalVolume).divide(hand, RoundingMode.HALF_UP));
                taxTransferDataMessage.setTotalAmount(new BigDecimal(totalAmount).divide(hand, RoundingMode.HALF_UP));
                // 如果说是外部平台的话 加入到一个新的缓存
                log.info("外部平台密文透传8c13 数据解密成功,解密透传数据存入缓存：{}", taxTransferDataMessage);
                redisCache.setCacheObject(
                    String.format(DeviceRedisEnum.TAX_CIPHERTEXT_OUT_RESULT.getKey(), ciphertextData.getPlatform()),
                        taxTransferDataMessage, DeviceRedisEnum.TAX_CIPHERTEXT_OUT_RESULT.getExpireTime(), TimeUnit.SECONDS);
            }
            else
            {
                String param = redisCache.getCacheObject(
                    String.format(DeviceRedisEnum.PASS_TAX_DATA_GUN_NO.getKey(), gatewayNo, collectorNo, taxNo));
                String[] split = param.split(ApiPathConstants.UNDERLINE);

                TaxMonthDataMessage taxMonthDataMessage = new TaxMonthDataMessage();
                taxMonthDataMessage.setVolume(new BigDecimal(totalVolume).divide(hand, RoundingMode.HALF_UP));
                taxMonthDataMessage.setAmount(new BigDecimal(totalAmount).divide(hand, RoundingMode.HALF_UP));
                log.info("密文透传8c13 数据解密成功,解密透传数据存入缓存：{}", taxMonthDataMessage);
                redisCache.setCacheObject(
                    String.format(DeviceRedisEnum.PASS_TAX_DATA.getKey(), gatewayNo, collectorNo, taxNo, split[0], split[1]),
                        taxMonthDataMessage, DeviceRedisEnum.PASS_TAX_DATA.getExpireTime(), TimeUnit.SECONDS);
            }
        }
        else if (result == 1 && env == 0)
        {
            // 服务器保存数据
            CiphertextData ciphertextData = redisCache.getCacheMapValue(DeviceRedisEnum.TAX_CIPHERTEXT_DATA_SEND.getKey(), key2);
            BigDecimal hand = new BigDecimal("100");
            body.readBytes(19);
            // 开始解析数据 累计值
            body.readBytes(7);
            String totalVolume = readASCII(body, 12);
            String totalAmount = readASCII(body, 12);
            body.readByte();
            // 开始解析交易值
            body.readBytes(7);
            body.readBytes(6);
            String volume = readASCII(body, 9);
            String amount = readASCII(body, 9);
            String price = readASCII(body, 4);

            TaxTransferDataMessage taxTransferDataMessage = new TaxTransferDataMessage();
            taxTransferDataMessage.setDeviceType(DeviceModelEnum.getTypeByModel(ciphertextData.getDeviceType()));
            taxTransferDataMessage.setGatewayNo(gatewayNo);
            taxTransferDataMessage.setCollectorNo(collectorNo);
            taxTransferDataMessage.setTaxNo(taxNo);
            taxTransferDataMessage.setGunNo(gunNo);
            taxTransferDataMessage.setSerialNo(serialNo);
            taxTransferDataMessage.setRaiseTime(ciphertextData.getRaiseTime());
            taxTransferDataMessage.setHangTime(ciphertextData.getHangTime());
            taxTransferDataMessage.setUnitPrice(new BigDecimal(price).divide(hand, RoundingMode.HALF_UP));
            taxTransferDataMessage.setVolume(new BigDecimal(volume).divide(hand, RoundingMode.HALF_UP));
            taxTransferDataMessage.setAmount(new BigDecimal(amount).divide(hand, RoundingMode.HALF_UP));
            taxTransferDataMessage.setTotalVolume(new BigDecimal(totalVolume).divide(hand, RoundingMode.HALF_UP));
            taxTransferDataMessage.setTotalAmount(new BigDecimal(totalAmount).divide(hand, RoundingMode.HALF_UP));
            taxTransferDataMessage.setDataTime(ciphertextData.getDateTime());
            //删除队列
            log.info("数据解密成功,调用业务服务保存数据");
            redisCache.deleteCacheMapValue(DeviceRedisEnum.TAX_CIPHERTEXT_DATA_SEND.getKey(), key2);
            if (StringUtils.isNotBlank(ciphertextData.getPlatform()))
            {
                // 如果说是外部平台的话 加入到一个新的缓存
                redisCache.setCacheObject(
                    String.format(DeviceRedisEnum.TAX_CIPHERTEXT_OUT_RESULT.getKey(), ciphertextData.getPlatform()),
                        taxTransferDataMessage, DeviceRedisEnum.TAX_CIPHERTEXT_OUT_RESULT.getExpireTime(), TimeUnit.SECONDS);
            }
            else
            {
                taxTransferDataService.saveTaxTransferData(taxTransferDataMessage);
            }
        }
        else if (result == 1 && env == 1)
        {
            // 返回给客户端测试板
            byte[] bytes = new byte[copyBuf.readableBytes() - 2];
            copyBuf.getBytes(copyBuf.readerIndex(), bytes);

            CiphertextData ciphertextData = redisCache.getCacheMapValue(DeviceRedisEnum.TAX_CIPHERTEXT_DATA_SEND.getKey(), key2);

            CiphertextDataDown request = new CiphertextDataDown();
            request.setCiphertextData(bytes);
            request.setDeviceSn(ciphertextData.getDeviceSn());
            request.setDeviceType(ciphertextData.getDeviceType());
            String key = MsgHandlerUtil.getEncoderKey(MsgTypeEnum.CIPHERTEXT_DATA_DECRYPT_DOWN);
            IEncoder<CiphertextDataDown> encoder = (IEncoder<CiphertextDataDown>) handlerManager.getEncoder(key);
            encoder.encode(request);

            log.info("数据解密成功,返回客户端解密后数据");
            // 删除队列
            redisCache.deleteCacheMapValue(DeviceRedisEnum.TAX_CIPHERTEXT_DATA_SEND.getKey(), key2);
        }
        else if (result == 2 || result == 4 || result == 6 || result == 7)
        {
            // 超时
            // 删除发送队列
            CiphertextData ciphertextData = redisCache.getCacheMapValue(DeviceRedisEnum.TAX_CIPHERTEXT_DATA_SEND.getKey(), key2);
            redisCache.deleteCacheMapValue(DeviceRedisEnum.TAX_CIPHERTEXT_DATA_SEND.getKey(), key2);
            if (decryptDeviceConfig.getDefaultFailTimes() > ciphertextData.getSendTimes())
            {
                // 插入失败队列
                ciphertextData.setKey1(DeviceRedisEnum.TAX_CIPHERTEXT_DATA_FAIL.getKey());
                redisCache.setCacheMapValue(DeviceRedisEnum.TAX_CIPHERTEXT_DATA_FAIL.getKey(), key2, ciphertextData);
                log.info("解密设备返回数据解密超时，加入到失败队列等待下次发送，数据标志:{}", key2);
            }
            else
            {
                log.info("解密设备返回数据解密超时，已过最大失败次数，数据删除，数据标志:{}", key2);
            }
        }
        else
        {
            // 解密失败
            redisCache.deleteCacheMapValue(DeviceRedisEnum.TAX_CIPHERTEXT_DATA_SEND.getKey(), key2);

            byte[] bytes = new byte[copyBuf.readableBytes() - 2];
            copyBuf.getBytes(copyBuf.readerIndex(), bytes);
            String payloadHex = MessageHandler.bytesToHexLog(bytes);
            log.info("数据解密失败：{}", payloadHex);
        }

        return null;
    }
}
