package com.fzm.mall.server.front.mq.consumer;

import cn.fzm.chain.simplesdk.client.MainChainClient;
import cn.fzm.chain.simplesdk.constant.TxStatusEnum;
import cn.fzm.chain.simplesdk.model.TxResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fzm.mall.server.front.asset.model.UserAsset;
import com.fzm.mall.server.front.asset.model.UserAssetRecord;
import com.fzm.mall.server.front.asset.model.vo.asset.UserAssetVo;
import com.fzm.mall.server.front.asset.service.IUserAssetRecordService;
import com.fzm.mall.server.front.asset.service.IUserAssetService;
import com.fzm.mall.server.front.constant.MALLGlobalConfig;
import com.fzm.mall.server.front.enums.QueueTTLTypeEnum;
import com.fzm.mall.server.front.mq.MsgProducer;
import com.fzm.mall.server.front.order.model.po.TranDto;
import io.netty.util.internal.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

/**
 * 提币确认
 *
 * @author tdz
 * @date 创建时间：2021年05月26日
 */
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AssetTranConsumer {
    private final MainChainClient mainChainClient;
    private final MsgProducer msgProducer;
    private final IUserAssetRecordService userAssetRecordService;
    private final IUserAssetService userAssetService;
    private final RedisTemplate<String, String> redisTemplate;


    @RabbitListener(queues = MALLGlobalConfig.projectMq+".asset.tran.queue")
    public void receiver(String message) {
        if (StringUtil.isNullOrEmpty(message)) {
            return;
        }
        TranDto tranDto = JSON.parseObject(message, TranDto.class);
        if (tranDto == null) {
            log.error("AssetTranConsumer :" + message + "-tranDto == null");
            return;
        }
        Boolean isChain = tranDto.getIsChain();
        if (isChain == null) {
            return;
        } else if (!isChain) {
            commit(tranDto);
        } else if (isChain) {
            String hash = tranDto.getHash();
            BoundValueOperations<String, String> operations = redisTemplate.boundValueOps(hash);
            operations.increment(1);
            try {
                TxResult txResult = mainChainClient.cycleConfirmTxWithHash(hash, false, 1000);
                //TxResult txResult = mainChainClient.confirmTxWithRealTxHash(hash);
                TxStatusEnum txStatusEnum = txResult.getStatus();
                System.out.println(txResult.getErrMsg());
                switch (txStatusEnum) {
                    case SUCCESS:
                        commit(tranDto);
                        break;
                    case FAIL:
                        rollBack(tranDto);
                        break;
                    default:
                        resend(tranDto);
                        break;
                }
            } catch (Exception e) {
                String value = operations.get();
                StackTraceElement[] stackTrace = e.getStackTrace();
                StringBuilder sb = new StringBuilder();
                for (StackTraceElement stackTraceElement : stackTrace) {
                    sb.append(stackTraceElement.getFileName()).append("*").append(stackTraceElement.getLineNumber()).append("*");
                }
                log.error("AssetTranConsumer-message:" + message + "-e" + sb.toString());
                if (Integer.parseInt(value) < 6) {
                    msgProducer.sendTTL(message, QueueTTLTypeEnum.MALL_ASSET_TRAN_TTL,
                            5 * 1000);
                } else {
                    return;
                }
            }
        }
    }

    @Transactional
    private void commit(TranDto tranDto) {
        //回收确认
        try {
            UserAssetRecord assetRecord = userAssetRecordService.getById(tranDto.getId());
            assetRecord.setStatus(2);//成功
            userAssetRecordService.updateById(assetRecord);
            //减去冻结资产
            UserAssetVo ownAsset = userAssetService.getOwnAsset(assetRecord.getUid(), tranDto.getCoin());
            ownAsset.setFrozen(ownAsset.getFrozen().subtract(tranDto.getAmount()));
            UserAsset newAsset = new UserAsset();
            BeanUtils.copyProperties(ownAsset, newAsset);
            userAssetService.saveOrUpdate(newAsset);
            return;
        } catch (Exception e) {
            log.error("AssetTranConsumer-e" + e.toString());
            return;
        }

    }

    @Transactional
    private void rollBack(TranDto tranDto) {

        log.error("withdraw fail,hash:" + tranDto.getHash());
        //tranDto.setCoin("YHTY");
        String hash = mainChainClient.mainTranToken(tranDto.getFromAddr(), null, tranDto.getToAddr(), tranDto.getAmount(), tranDto.getCoin());
        tranDto.setHash(hash);
        msgProducer.sendTTL(JSON.toJSONString(tranDto), QueueTTLTypeEnum.MALL_ASSET_TRAN_TTL,
                5 * 1000);

    }

    private void resend(TranDto tranDto) {
        log.error("withdraw queue resend:" + tranDto);
        if (StringUtil.isNullOrEmpty(tranDto.getHash())) {
            String hash = mainChainClient.mainTranToken(tranDto.getFromAddr(), null, tranDto.getToAddr(), tranDto.getAmount(), tranDto.getCoin());
            tranDto.setHash(hash);
        }
        msgProducer.sendTTL(JSON.toJSONString(tranDto), QueueTTLTypeEnum.MALL_ASSET_TRAN_TTL,
                5 * 1000);
    }

}
