package com.liquidnet.service.galaxy.router.zxin.biz;

import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.common.third.zxlnft.biz.ZxlnftBiz;
import com.liquidnet.common.third.zxlnft.config.ZxlnftConfig;
import com.liquidnet.common.third.zxlnft.constant.ZxlErrorEnum;
import com.liquidnet.common.third.zxlnft.constant.ZxlnftEnum;
import com.liquidnet.common.third.zxlnft.dto.*;
import com.liquidnet.common.third.zxlnft.exception.ZxlNftException;
import com.liquidnet.common.third.zxlnft.util.ZxlnftSdkUtil;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.galaxy.biz.GalaxyBeanTransferBiz;
import com.liquidnet.service.galaxy.biz.GalaxyEnumBiz;
import com.liquidnet.service.galaxy.constant.GalaxyEnum;
import com.liquidnet.service.galaxy.constant.GalaxyErrorEnum;
import com.liquidnet.service.galaxy.dto.bo.GalaxyNftOrderBo;
import com.liquidnet.service.galaxy.dto.bo.GalaxySeriesNftInfoBo;
import com.liquidnet.service.galaxy.dto.bo.GalaxyTransferNftInfoBo;
import com.liquidnet.service.galaxy.dto.bo.GalaxyUserInfoBo;
import com.liquidnet.service.galaxy.dto.param.*;
import com.liquidnet.service.galaxy.exception.GalaxyNftPublishException;
import com.liquidnet.service.galaxy.utils.GalaxyDataUtils;
import com.liquidnet.service.galaxy.utils.QueueUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author AnJiabin <anjiabin@zhengzai.tv>
 * @version V1.0
 * @Description: TODO
 * @class: ZxinTradeBiz
 * @Package com.liquidnet.service.galaxy.router.zxin.biz
 * @Copyright: LightNet @ Copyright (c) 2021
 * @date 2022/3/15 13:08
 */
@Slf4j
@Component
public class ZxinTradeBiz {
    @Autowired
    private ZxlnftSdkUtil zxlnftSdkUtil;

    @Autowired
    private ZxlnftBiz zxlnftBiz;

    @Autowired
    private ZxlnftConfig zxlnftConfig;

    @Autowired
    private GalaxyDataUtils dataUtils;

    @Autowired
    private GalaxyBeanTransferBiz galaxyBeanTransferBiz;

    @Autowired
    private ZxinPublishBiz zxinPublishBiz;

    @Autowired
    private ZxinTradeCommonBiz zxinTradeCommonBiz;

    @Autowired
    private QueueUtil queueUtil;


    public ResponseDto<GalaxyNftBuyRespDto> nftBuy(GalaxyNftBuyReqDto nftBuyReqDto){
        //获取订单信息
        GalaxyNftOrderBo nftOrderBo = dataUtils.getNftOrderBo(nftBuyReqDto.getRouterType(),nftBuyReqDto.getNftOrderPayId());
        if(StringUtil.isNotNull(nftOrderBo)&&StringUtil.isNotEmpty(nftOrderBo.getNftBuyTaskId())){
            return ResponseDto.failure(GalaxyErrorEnum.NFT_BUY_TASK_HAVE_EXIST.getCode(), GalaxyErrorEnum.NFT_BUY_TASK_HAVE_EXIST.getMessage());
        }

        //获取用户信息
        GalaxyUserInfoBo userInfoBo = dataUtils.getGalaxyUserInfo(nftBuyReqDto.getRouterType(),nftBuyReqDto.getUserId());

        //获取sku信息
        GalaxySeriesNftInfoBo seriesNftInfoBo = dataUtils.getSeriesNftInfoBo(nftBuyReqDto.getRouterType(),nftBuyReqDto.getSkuId());


        //返回参数nftId
        String nftId = null;
        if(StringUtil.isNotNull(nftOrderBo)){
            nftId = nftOrderBo.getNftId();
        }

        if(StringUtil.isNotEmpty(nftId)){
            //执行购买逻辑
            GalaxyNftBuyRespDto nftBuyRespDto = this.nftBuyBusiness(nftBuyReqDto.getRouterType(),nftId,userInfoBo,seriesNftInfoBo,nftOrderBo);
            return ResponseDto.success(nftBuyRespDto);
        }else{
            return ResponseDto.failure(GalaxyErrorEnum.NFT_BUY_FAIL.getCode(), GalaxyErrorEnum.NFT_BUY_FAIL.getMessage());
        }
    }

    public ResponseDto<GalaxyNftBuyResultQueryRespDto> nftBuyResultQuery(GalaxyNftBuyResultQueryReqDto reqDto) {
        //获取订单信息
        GalaxyNftOrderBo nftOrderBo = dataUtils.getNftOrderBo(reqDto.getRouterType(),reqDto.getNftOrderPayId());
        if(StringUtil.isNull(nftOrderBo)){
            return ResponseDto.failure(GalaxyErrorEnum.PUBLISH_ORDER_NOT_EXIST.getCode(), GalaxyErrorEnum.PUBLISH_ORDER_NOT_EXIST.getMessage());
        }

        if(StringUtil.isEmpty(nftOrderBo.getNftBuyTaskId())){
            return ResponseDto.failure(GalaxyErrorEnum.NFT_BUY_TASK_NOT_EXIST.getCode(), GalaxyErrorEnum.NFT_BUY_TASK_NOT_EXIST.getMessage());
        }
        //3.2.4查询NFT购买结果
        Nft044BuyResultReqDto nft044ReqDto = Nft044BuyResultReqDto.getNew();
        nft044ReqDto.setTaskId(nftOrderBo.getNftBuyTaskId());
        ZxlnftResponseDto<Nft044BuyResultRespDto> nft044RespDto = zxlnftSdkUtil.nft044BuyResult(nft044ReqDto);

        GalaxyNftBuyResultQueryRespDto resultQueryRespDto = GalaxyNftBuyResultQueryRespDto.getNew();
        if(nft044RespDto.isSuccess()){
            if(nft044RespDto.getData().getTaskStatus().toString().equals(ZxlnftEnum.TaskStatusEnum.TASK_SUCCESS.getCode())){
                Long nftBuyChainTimestamp = nft044RespDto.getData().getChainTimestamp();
                Integer nftBuyStatus = nft044RespDto.getData().getTaskStatus();
                String nftBuyTradeHash = nft044RespDto.getData().getTxHash();;
                String nftBuyPayTaskId = nft044RespDto.getData().getPayTaskId();
                //更新订单缓存数据状态
                if(StringUtil.isNotNull(nftBuyChainTimestamp)&&nftBuyChainTimestamp!=0){
                    //设置时间
                    String nftBuyChainTimestampStr = DateUtil.format(new Date(nftBuyChainTimestamp*1000),DateUtil.Formatter.yyyyMMddHHmmss);
                    nftOrderBo.setNftBuyChainTimestamp(nftBuyChainTimestampStr);
                }
                if(StringUtil.isNotNull(nftBuyStatus)){
                    //转换任务状态
                    String nftBuyStatusStr = GalaxyEnumBiz.getTaskStatusEnum(nftOrderBo.getRouterType(),nftBuyStatus.toString()).getCode();

                    nftOrderBo.setNftBuyStatus(nftBuyStatusStr);
                }
                nftOrderBo.setNftBuyTradeHash(nftBuyTradeHash);
                nftOrderBo.setNftBuyPayTaskId(nftBuyPayTaskId);
                nftOrderBo.setUpdatedAt(LocalDateTime.now());
                //先更新nft购买数据
                dataUtils.updateNftOrderBuyInfo(nftOrderBo.getRouterType(),nftOrderBo.getNftOrderPayId(),nftOrderBo);
            }else if(nft044RespDto.getData().getTaskStatus().toString().equals(ZxlnftEnum.TaskStatusEnum.TASK_FAIL.getCode())){
                Long nftBuyChainTimestamp = nft044RespDto.getData().getChainTimestamp();
                Integer nftBuyStatus = nft044RespDto.getData().getTaskStatus();
                //更新订单缓存数据状态
                if(StringUtil.isNotNull(nftBuyChainTimestamp)&&nftBuyChainTimestamp!=0){
                    //设置时间
                    String nftBuyChainTimestampStr = DateUtil.format(new Date(nftBuyChainTimestamp*1000),DateUtil.Formatter.yyyyMMddHHmmss);
                    nftOrderBo.setNftBuyChainTimestamp(nftBuyChainTimestampStr);
                }
                if(StringUtil.isNotNull(nftBuyStatus)){
                    //转换任务状态
                    String nftBuyStatusStr = GalaxyEnumBiz.getTaskStatusEnum(nftOrderBo.getRouterType(),nftBuyStatus.toString()).getCode();

                    nftOrderBo.setNftBuyStatus(nftBuyStatusStr);
                }
                nftOrderBo.setUpdatedAt(LocalDateTime.now());
                //先更新nft购买数据
                dataUtils.updateNftOrderBuyInfo(nftOrderBo.getRouterType(),nftOrderBo.getNftOrderPayId(),nftOrderBo);
            }
            resultQueryRespDto.setTaskStatus(Integer.parseInt(nftOrderBo.getNftBuyStatus()));
            resultQueryRespDto.setChainTimestamp(nftOrderBo.getNftBuyChainTimestamp());
            return ResponseDto.success(resultQueryRespDto);
        }else{
            return ResponseDto.failure(GalaxyErrorEnum.NFT_PUBLISH_AND_BUY_QUERY_FAIL.getCode(), GalaxyErrorEnum.NFT_PUBLISH_AND_BUY_QUERY_FAIL.getMessage());
        }

    }

    public ResponseDto<GalaxyNftBuyPayResultQueryRespDto> nftBuyPayResultQuery(GalaxyNftBuyPayResultQueryReqDto reqDto) {
        //获取订单信息
        GalaxyNftOrderBo nftOrderBo = dataUtils.getNftOrderBo(reqDto.getRouterType(),reqDto.getNftOrderPayId());
        if(StringUtil.isNull(nftOrderBo)){
            return ResponseDto.failure(GalaxyErrorEnum.PUBLISH_ORDER_NOT_EXIST.getCode(), GalaxyErrorEnum.PUBLISH_ORDER_NOT_EXIST.getMessage());
        }

        //3.2.5查询NFT购买支付结果
        Nft045BuyPayResultReqDto nft045ReqDto = Nft045BuyPayResultReqDto.getNew();
        nft045ReqDto.setTaskId(nftOrderBo.getNftBuyPayTaskId());
        ZxlnftResponseDto<Nft045BuyPayResultRespDto> nft045RespDto = zxlnftSdkUtil.nft045BuyPayResult(nft045ReqDto);

        GalaxyNftBuyPayResultQueryRespDto resultQueryRespDto = GalaxyNftBuyPayResultQueryRespDto.getNew();
        BeanUtil.copy(nft045RespDto.getData(),resultQueryRespDto);
        String nowTimeStr = DateUtil.format(new Date(nft045RespDto.getData().getChainTimestamp().longValue()*1000),DateUtil.Formatter.yyyyMMddHHmmss);
        //转换任务状态
        Integer taskStatus = Integer.valueOf(GalaxyEnumBiz.getTaskStatusEnum(reqDto.getRouterType(),nft045RespDto.getData().getTaskStatus().toString()).getCode());
        resultQueryRespDto.setTaskStatus(taskStatus);
        resultQueryRespDto.setChainTimestamp(nowTimeStr);
        return ResponseDto.success(resultQueryRespDto);
    }

    /**
     * NFT发行和购买
     * @param reqDto
     * @return
     */
    public ResponseDto<GalaxyNftPublishAndBuyResultQueryRespDto> nftPublishAndBuyResultQuery(GalaxyNftPublishAndBuyResultQueryReqDto reqDto) {
        //获取订单信息
        GalaxyNftOrderBo nftOrderBo = dataUtils.getNftOrderBo(reqDto.getRouterType(),reqDto.getNftOrderPayId());
        if(StringUtil.isNull(nftOrderBo)){
            return ResponseDto.failure(GalaxyErrorEnum.PUBLISH_ORDER_NOT_EXIST.getCode(), GalaxyErrorEnum.PUBLISH_ORDER_NOT_EXIST.getMessage());
        }

        /**
         * TODO 如果订单信息是购买失败，则直接调用至信链查询购买结果
         */
        //是否需要发起二次购买
        boolean isNeedSecondBuy = false;
        if(StringUtil.isNotEmpty(nftOrderBo.getNftPublishStatus())
                && (GalaxyEnum.TaskStatusEnum.INIT.getCode().equalsIgnoreCase(nftOrderBo.getNftPublishStatus())
                ||GalaxyEnum.TaskStatusEnum.PROCESSING.getCode().equalsIgnoreCase(nftOrderBo.getNftPublishStatus()))){
            //判断是否需要二次购买
            if(StringUtil.isEmpty(nftOrderBo.getNftPublishTaskId())){
                isNeedSecondBuy = true;
            }
            //执行nft发行结果查询
            GalaxyNftPublishResultQueryReqDto nftPublishResultQueryReqDto = GalaxyNftPublishResultQueryReqDto.getNew();
            nftPublishResultQueryReqDto.setNftOrderPayId(reqDto.getNftOrderPayId());
            nftPublishResultQueryReqDto.setRouterType(reqDto.getRouterType());
            ResponseDto<GalaxyNftPublishResultQueryRespDto> publishResultQueryRespDto = zxinPublishBiz.nftPublishResultQuery(nftPublishResultQueryReqDto);
        }else if(StringUtil.isNotEmpty(nftOrderBo.getNftBuyStatus())
                && (GalaxyEnum.TaskStatusEnum.INIT.getCode().equalsIgnoreCase(nftOrderBo.getNftBuyStatus())
                ||GalaxyEnum.TaskStatusEnum.PROCESSING.getCode().equalsIgnoreCase(nftOrderBo.getNftBuyStatus()))){
            //判断是否需要二次购买
            if(StringUtil.isEmpty(nftOrderBo.getNftBuyTaskId())){
                isNeedSecondBuy = true;
            }
            //执行nft购买结果查询
            GalaxyNftBuyResultQueryReqDto nftBuyResultQueryReqDto = GalaxyNftBuyResultQueryReqDto.getNew();
            nftBuyResultQueryReqDto.setNftOrderPayId(reqDto.getNftOrderPayId());
            nftBuyResultQueryReqDto.setRouterType(reqDto.getRouterType());
            ResponseDto<GalaxyNftBuyResultQueryRespDto> buyResultQueryRespDto= this.nftBuyResultQuery(nftBuyResultQueryReqDto);
        }

        //判断是否需要二次购买
//        if(isNeedSecondBuy){
//            GalaxyNftPublishAndBuyReqDto galaxyNftPublishAndBuyReqDto = GalaxyNftPublishAndBuyReqDto.getNew();
//            BeanUtil.copy(reqDto,galaxyNftPublishAndBuyReqDto);
//            galaxyNftPublishAndBuyReqDto.setSkuId(nftOrderBo.getSkuId());
//            galaxyNftPublishAndBuyReqDto.setBuyTimestamp(DateUtil.getNowTime());
//            queueUtil.sendMsgByRedis(MQConst.GalaxyQueue.JSON_NFT_PUBLISH_AND_BUY.getKey(), JsonUtils.toJson(galaxyNftPublishAndBuyReqDto));
//        }

        GalaxyNftPublishAndBuyResultQueryRespDto resultQueryRespDto = GalaxyNftPublishAndBuyResultQueryRespDto.getNew();
        if(nftOrderBo.getNftPublishStatus().equalsIgnoreCase(GalaxyEnum.TaskStatusEnum.TASK_SUCCESS.getCode())&&
                nftOrderBo.getNftBuyStatus().equalsIgnoreCase(GalaxyEnum.TaskStatusEnum.TASK_SUCCESS.getCode())){
            BeanUtil.copy(nftOrderBo,resultQueryRespDto);
            return ResponseDto.success(resultQueryRespDto);
        }
        return ResponseDto.failure(GalaxyErrorEnum.NFT_PUBLISH_AND_BUY_QUERY_FAIL.getCode(),GalaxyErrorEnum.NFT_PUBLISH_AND_BUY_QUERY_FAIL.getMessage(),resultQueryRespDto);
    }

    /**
     * NFT发行和购买批量查询
     * @param reqDto
     * @return
     */
    public ResponseDto<GalaxyNftPublishAndBuyRouterBatchQueryRespDto> nftPublishAndBuyResultBatchQuery(GalaxyNftPublishAndBuyRouterBatchQueryReqDto reqDto) {
        List<String> nftOrderPayIdList = reqDto.getNftOrderPayIdList();
        List<GalaxyNftPublishAndBuyResultQueryRespDto> buyInfoList = new ArrayList<>();
        for(int i=0;i<nftOrderPayIdList.size();i++){
            GalaxyNftPublishAndBuyResultQueryReqDto resultQueryReqDto = GalaxyNftPublishAndBuyResultQueryReqDto.getNew();
            resultQueryReqDto.setUserId(reqDto.getUserId());
            resultQueryReqDto.setNftOrderPayId(nftOrderPayIdList.get(i));
            resultQueryReqDto.setRouterType(reqDto.getRouterType());
            ResponseDto<GalaxyNftPublishAndBuyResultQueryRespDto> resultQueryRespDto = this.nftPublishAndBuyResultQuery(resultQueryReqDto);
            if(resultQueryRespDto.isSuccess()){
                buyInfoList.add(resultQueryRespDto.getData());
            }
        }
        GalaxyNftPublishAndBuyRouterBatchQueryRespDto routerBatchQueryRespDto = GalaxyNftPublishAndBuyRouterBatchQueryRespDto.getNew();
        routerBatchQueryRespDto.setRouterType(reqDto.getRouterType());
        routerBatchQueryRespDto.setBuyInfoList(buyInfoList);
        return ResponseDto.success(routerBatchQueryRespDto);
    }

    private GalaxyNftBuyRespDto nftBuyBusiness(String routerType,String nftId,GalaxyUserInfoBo userInfoBo, GalaxySeriesNftInfoBo seriesNftInfoBo,GalaxyNftOrderBo nftOrderBo){
//        3.2.2调用购买NFT接口
        Nft043BuyReqDto nft043BuyReqDto = Nft043BuyReqDto.getNew();
        nft043BuyReqDto.setNftId(nftId);
        nft043BuyReqDto.setApplyScore(seriesNftInfoBo.getSellCount().intValue());
        try {
            nft043BuyReqDto.setReceiverPubKey(BASE64Util.decode(userInfoBo.getUserPubKey()));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        nft043BuyReqDto.setPointReceiverAddr(userInfoBo.getBlockChainAddress());
        nft043BuyReqDto.setOfferCount(seriesNftInfoBo.getSellCount().longValue());
        nft043BuyReqDto.setOperateId(IDGenerator.get32UUID());

        /**
         * 接收人的私钥签名，签名对象是(platformPubKey_receiverPubKey_pointReceiverAddr_applyScore_接口名_nftId_offerCount_operateId)
         * 接口名：buy_nft
         */
        String signMetaData = zxlnftConfig.getNftPlatformPubKey()
                .concat("_").concat(nft043BuyReqDto.getReceiverPubKey())
                .concat("_").concat(nft043BuyReqDto.getPointReceiverAddr())
                .concat("_").concat(nft043BuyReqDto.getApplyScore().toString())
                .concat("_").concat("buy_nft")
                .concat("_").concat(nft043BuyReqDto.getNftId())
                .concat("_").concat(nft043BuyReqDto.getOfferCount().toString())
                .concat("_").concat(nft043BuyReqDto.getOperateId());
        String signature = null;
        try {
            signature = zxlnftBiz.createSign(BASE64Util.decode(userInfoBo.getUserPriKey()),signMetaData);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        nft043BuyReqDto.setSignature(signature);

        String nftBuyTaskId = null;
        ZxlnftResponseDto<Nft043BuyRespDto> nft043RespDto = zxlnftSdkUtil.nft043Buy(nft043BuyReqDto);
        if(nft043RespDto.isSuccess()){
            nftBuyTaskId = nft043RespDto.getData().getTaskId();
        }else{
            throw new LiquidnetServiceException(nft043RespDto.getCode(),nft043RespDto.getMessage());
        }

        //更新缓存数据状态
        nftOrderBo.setNftBuyTaskId(nftBuyTaskId);
        nftOrderBo.setNftBuyStatus(GalaxyEnum.TaskStatusEnum.PROCESSING.getCode());
        dataUtils.updateNftOrderBuyInfo(routerType,nftOrderBo.getNftOrderPayId(),nftOrderBo);

        GalaxyNftBuyRespDto nftBuyRespDto = GalaxyNftBuyRespDto.getNew();
        nftBuyRespDto.setUserId(userInfoBo.getUserId());
        nftBuyRespDto.setNftId(null);
        return nftBuyRespDto;
    }

    /**
     * 发行和购买
     * @param reqDto
     * @return
     */
    public ResponseDto<GalaxyNftPublishAndBuyRespDto> nftPublishAndBuy(GalaxyNftPublishAndBuyReqDto reqDto) {
        return zxinTradeCommonBiz.nftPublishAndBuy(reqDto);
    }

    /**
     * nft转让
     * @param reqDto
     * @return
     */
    public ResponseDto<GalaxyNftTransferRespDto> nftTransfer(GalaxyNftTransferReqDto reqDto) {
        log.info("nftTransfer request param:{}",JsonUtils.toJson(reqDto));

        //获取用户信息
        GalaxyUserInfoBo userInfoBo = dataUtils.getGalaxyUserInfo(reqDto.getRouterType(),reqDto.getUserId());
        if(StringUtil.isNull(userInfoBo)){
            log.error("开始执行 nftTransfer nft owner not exist error msg:{}",GalaxyErrorEnum.NFT_TRANSFER_FAIL_OWNER_NOT_EXIST.getMessage());
            return ResponseDto.failure(GalaxyErrorEnum.NFT_TRANSFER_FAIL_OWNER_NOT_EXIST.getCode(), GalaxyErrorEnum.NFT_TRANSFER_FAIL_OWNER_NOT_EXIST.getMessage());
        }

        //获取用户信息
        GalaxyUserInfoBo receiveUserInfoBo = dataUtils.getGalaxyUserInfo(reqDto.getRouterType(),reqDto.getReceiveUserId());
        if(StringUtil.isNull(userInfoBo)){
            log.error("开始执行 nftTransfer nft receiver not exist error msg:{}",GalaxyErrorEnum.NFT_TRANSFER_FAIL_RECEIVER_NOT_EXIST.getMessage());
            return ResponseDto.failure(GalaxyErrorEnum.NFT_TRANSFER_FAIL_RECEIVER_NOT_EXIST.getCode(), GalaxyErrorEnum.NFT_TRANSFER_FAIL_RECEIVER_NOT_EXIST.getMessage());
        }

        try{
            GalaxyTransferNftInfoBo transferNftInfoBo = dataUtils.getGalaxyTransferNftInfoBo(reqDto.getRouterType(),reqDto.getTransOrderId());
            //初始化转让信息
            if(transferNftInfoBo==null){
                transferNftInfoBo = galaxyBeanTransferBiz.buildTransferNftInfoBo(reqDto,userInfoBo,receiveUserInfoBo);
                dataUtils.setGalaxyTransferNftInfoBo(reqDto.getRouterType(),reqDto.getTransOrderId(),transferNftInfoBo);
            }else{
                //判断藏品当前拥有者是否匹配
                if(transferNftInfoBo.getUserId().equalsIgnoreCase(reqDto.getUserId())){
                    if(transferNftInfoBo.getTransferStatus().equalsIgnoreCase(GalaxyEnum.NftTransferStatusEnum.PROCESSING.getCode())){
                        transferNftInfoBo.setErrorCode(GalaxyErrorEnum.NFT_TRANSFERING_ERROR.getCode());
                        transferNftInfoBo.setErrorMsg(GalaxyErrorEnum.NFT_TRANSFERING_ERROR.getMessage());
                        transferNftInfoBo.setUpdatedAt(DateUtil.getNowTime());
                        dataUtils.updateTransferNftInfoBo(reqDto.getRouterType(),reqDto.getTransOrderId(),transferNftInfoBo);

                        return ResponseDto.failure(GalaxyErrorEnum.NFT_TRANSFERING_ERROR.getCode(), GalaxyErrorEnum.NFT_TRANSFERING_ERROR.getMessage());
                    }else if(transferNftInfoBo.getTransferStatus().equalsIgnoreCase(GalaxyEnum.NftTransferStatusEnum.SUCCESS.getCode())){
                        GalaxyNftTransferRespDto galaxyNftTransferRespDto = galaxyBeanTransferBiz.buildNftTransferRespDto(reqDto,userInfoBo,receiveUserInfoBo,transferNftInfoBo);
                        return ResponseDto.success(galaxyNftTransferRespDto);
                    }else if(transferNftInfoBo.getTransferStatus().equalsIgnoreCase(GalaxyEnum.NftTransferStatusEnum.FAIL.getCode())){
                        return ResponseDto.failure(GalaxyErrorEnum.NFT_TRANSFER_FAIL.getCode(), GalaxyErrorEnum.NFT_TRANSFER_FAIL.getMessage());
                    }
                }else{
                    transferNftInfoBo.setErrorCode(GalaxyErrorEnum.NFT_TRANSFER_OWNER_MATCH_ERROR.getCode());
                    transferNftInfoBo.setErrorMsg(GalaxyErrorEnum.NFT_TRANSFER_OWNER_MATCH_ERROR.getMessage());
                    transferNftInfoBo.setUpdatedAt(DateUtil.getNowTime());
                    dataUtils.updateTransferNftInfoBo(reqDto.getRouterType(),reqDto.getTransOrderId(),transferNftInfoBo);
                    return ResponseDto.failure(GalaxyErrorEnum.NFT_TRANSFER_OWNER_MATCH_ERROR.getCode(), GalaxyErrorEnum.NFT_TRANSFER_OWNER_MATCH_ERROR.getMessage());
                }
            }

            //nft信息核对
            if(StringUtil.isNotEmpty(reqDto.getNftId())){
                boolean checkNftOwnerFlag = this.checkNftOwner(userInfoBo,reqDto.getNftId());
                log.info("nftTransfer checkNftOwnerFlag:{}",checkNftOwnerFlag);
                //拥有者匹配 可以转让
                if(checkNftOwnerFlag){
                    //定义返回参数
                    String nftTransferTaskId = null;
                    Long nftTransferChainTimestamp = null;
                    Integer nftTransferStatus = null;
                    String nftTransferTradeHash = null;
                    try {
                        //操作者的公钥和私钥
                        String pubKey = BASE64Util.decode(userInfoBo.getUserPubKey());
                        String priKey = BASE64Util.decode(userInfoBo.getUserPriKey());
                        //nft接收者的地址
                        String receiverAddr = receiveUserInfoBo.getBlockChainAddress();
                        //要转移的nftId
                        String nftId = reqDto.getNftId();
                        //请求ID，每个请求需要填唯一的ID，重复请求用相同的id
                        String operateId = IDGenerator.get32UUID();


                        /**
                         * 操作者的私钥签名，签名对象是(pubKey_receiverAddr_接口名_nftId_operateId)
                         * 接口名：nft_transfer
                         */
                        String signMetaData = pubKey
                                .concat("_").concat(receiverAddr)
                                .concat("_").concat("nft_transfer")
                                .concat("_").concat(nftId)
                                .concat("_").concat(operateId);

                        //操作者的私钥签名，签名对象是(pubKey_receiverAddr_接口名_nftId_operateId)
                        String signature = zxlnftBiz.createSign(priKey,signMetaData);


                        Nft046TransferReqDto nft046TransferReqDto = Nft046TransferReqDto.getNew();
                        nft046TransferReqDto.setPubKey(pubKey);
                        nft046TransferReqDto.setReceiverAddr(receiverAddr);
                        nft046TransferReqDto.setNftId(nftId);
                        nft046TransferReqDto.setOperateId(operateId);
                        nft046TransferReqDto.setSignature(signature);

                        ZxlnftResponseDto<Nft046TransferRespDto> nft046TransferResp = zxlnftSdkUtil.nft046TransferV2(nft046TransferReqDto);
                        Nft046TransferRespDto nft046TransferRespDto = null;
                        if(nft046TransferResp.isSuccess()){
                            nft046TransferRespDto = nft046TransferResp.getParseData(Nft046TransferRespDto.class);
                            if(StringUtil.isNotNull(nft046TransferRespDto)&&StringUtil.isNotEmpty(nft046TransferRespDto.getTaskId())){
                                //获取任务id
                                nftTransferTaskId = nft046TransferRespDto.getTaskId();
                                transferNftInfoBo.setNftTransferTaskId(nftTransferTaskId);
                            }
                        }else{
                            //更新转让状态和拥有者信息(只有成功才更新拥有者信息)
                            transferNftInfoBo.setTransferStatus(GalaxyEnum.NftTransferStatusEnum.FAIL.getCode());
                            transferNftInfoBo.setErrorCode(nft046TransferResp.getCode());
                            transferNftInfoBo.setErrorMsg(nft046TransferResp.getMessage());
                            transferNftInfoBo.setUpdatedAt(DateUtil.getNowTime());
                            dataUtils.updateTransferNftInfoBo(reqDto.getRouterType(),reqDto.getTransOrderId(),transferNftInfoBo);
                        }

                        if (StringUtil.isNotEmpty(nftTransferTaskId)){
                            try{
                                Nft049TransferResultReqDto nft049TransferResultReqDto = Nft049TransferResultReqDto.getNew();
                                nft049TransferResultReqDto.setOperatorPubKey(BASE64Util.decode(userInfoBo.getUserPubKey()));
                                nft049TransferResultReqDto.setTaskId(nftTransferTaskId);

                                int count = 0;
                                long timeStart = System.currentTimeMillis();
                                while (StringUtil.isEmpty(nftTransferTradeHash)) {
                                    Thread.sleep(500l);
                                    count++;
                                    ZxlnftResponseDto<Nft049TransferResultRespDto> nft049ZxlnftRespDto = zxlnftSdkUtil.nft049TransferResult(nft049TransferResultReqDto);
                                    if(!nft049ZxlnftRespDto.isSuccess()){
                                        throw new ZxlNftException(ZxlErrorEnum.SYSTEM_ERROR.getCode(),ZxlErrorEnum.SYSTEM_ERROR.getMsg());
                                    }
                                    log.info("=======执行第{}次查询,taskId:{}", count, nft049TransferResultReqDto.getTaskId());
                                    if (nft049ZxlnftRespDto.getData().getTaskStatus().toString().equals(ZxlnftEnum.TaskStatusEnum.TASK_SUCCESS.getCode())) {
                                        nftTransferChainTimestamp = nft049ZxlnftRespDto.getData().getChainTimestamp();
                                        nftTransferStatus = nft049ZxlnftRespDto.getData().getTaskStatus();
                                        nftTransferTradeHash = nft049ZxlnftRespDto.getData().getTxHash();
                                    } else if (nft049ZxlnftRespDto.getData().getTaskStatus().toString().equals(ZxlnftEnum.TaskStatusEnum.TASK_FAIL.getCode())) {
                                        log.info("任务执行失败！taskId:{}", nft049TransferResultReqDto.getTaskId());
                                        nftTransferStatus = nft049ZxlnftRespDto.getData().getTaskStatus();
                                        //转让失败
                                        throw new GalaxyNftPublishException(GalaxyErrorEnum.NFT_TRANSFER_FAIL.getCode(), "nft049TransferResult_resp:"+GalaxyErrorEnum.NFT_TRANSFER_FAIL.getMessage());
                                    }else if(nft049ZxlnftRespDto.getData().getTaskStatus().toString().equals(ZxlnftEnum.TaskStatusEnum.PROCESSING.getCode())){
                                        log.info("任务执行中！taskId:{}", nft049TransferResultReqDto.getTaskId());
                                        nftTransferStatus = nft049ZxlnftRespDto.getData().getTaskStatus();
                                    }

                                    if (count == 20) {
                                        log.info("=======查询共20次，跳出循环！taskId:{}", nft049TransferResultReqDto.getTaskId());
                                        break;
                                    }
                                }

                                log.info("总共执行了{}次查询 总耗时:{} MS", count, (System.currentTimeMillis() - timeStart));
                            }catch (GalaxyNftPublishException e){
                                throw new GalaxyNftPublishException(e.getCode(),e.getMessage());
                            }catch(Exception e){
                                log.error(e.getMessage(),e);
                                throw new GalaxyNftPublishException(GalaxyErrorEnum.NFT_TRANSFER_ERROR.getCode(),"nft049TransferResult_exception:"+e.getMessage());
                            }

                            //更新转让状态和拥有者信息(只有成功才更新拥有者信息)
                            if(StringUtil.isNotNull(nftTransferChainTimestamp)){
                                //设置时间
                                String nftTransferChainTimestampStr = DateUtil.format(new Date(nftTransferChainTimestamp*1000),DateUtil.Formatter.yyyyMMddHHmmss);
                                transferNftInfoBo.setNftTransferChainTimestamp(nftTransferChainTimestampStr);
                            }
                            if(StringUtil.isNotNull(nftTransferStatus)){
                                //转换任务状态
                                String nftTransferStatusStr = GalaxyEnumBiz.getTransStatusEnum(reqDto.getRouterType(),nftTransferStatus.toString()).getCode();
                                transferNftInfoBo.setTransferStatus(nftTransferStatusStr);
                            }
                            transferNftInfoBo.setTransferHash(nftTransferTradeHash);
                            transferNftInfoBo.setOwnerUserId(transferNftInfoBo.getReceiveUserId());
                            transferNftInfoBo.setOwnerAddress(transferNftInfoBo.getReceiveAddress());
                            transferNftInfoBo.setUpdatedAt(DateUtil.getNowTime());
                            dataUtils.updateTransferNftInfoBo(reqDto.getRouterType(),reqDto.getTransOrderId(),transferNftInfoBo);

                            //构造返回结果
                            GalaxyNftTransferRespDto galaxyNftTransferRespDto = galaxyBeanTransferBiz.buildNftTransferRespDto(reqDto,userInfoBo,receiveUserInfoBo,transferNftInfoBo);
                            return ResponseDto.success(galaxyNftTransferRespDto);
                        }else{
                            throw new GalaxyNftPublishException(GalaxyErrorEnum.NFT_TRANSFER_ERROR.getCode(),"nft049TransferResult_resp:taskId : "+nftTransferTaskId);
                        }
                    }catch (ZxlNftException e) {
                        log.error("biz error msg "+e.getMessage(),e);
                    }catch (Exception e) {
                        log.error("sys error msg "+e.getMessage(),e);
                    }
                }else{
                    //更新转让状态和拥有者信息(只有成功才更新拥有者信息)
                    transferNftInfoBo.setTransferStatus(GalaxyEnum.NftTransferStatusEnum.FAIL.getCode());
                    transferNftInfoBo.setErrorCode(GalaxyErrorEnum.NFT_TRANSFER_OWNER_MATCH_ERROR.getCode());
                    transferNftInfoBo.setErrorMsg(GalaxyErrorEnum.NFT_TRANSFER_OWNER_MATCH_ERROR.getMessage());
                    transferNftInfoBo.setUpdatedAt(DateUtil.getNowTime());
                    dataUtils.updateTransferNftInfoBo(reqDto.getRouterType(),reqDto.getTransOrderId(),transferNftInfoBo);
                    return ResponseDto.failure(GalaxyErrorEnum.NFT_TRANSFER_OWNER_MATCH_ERROR.getCode(), GalaxyErrorEnum.NFT_TRANSFER_OWNER_MATCH_ERROR.getMessage());
                }
            }
        }catch (ZxlNftException e) {
            log.error("biz error msg "+e.getMessage(),e);
        }catch (Exception e) {
            log.error("sys error msg "+e.getMessage(),e);
        }
        return ResponseDto.failure(GalaxyErrorEnum.NFT_TRANSFER_FAIL.getCode(), GalaxyErrorEnum.NFT_TRANSFER_FAIL.getMessage());
    }

    /**
     * nft转让结果查询
     * @param reqDto
     * @return
     */
    public ResponseDto<GalaxyNftTransferQueryRespDto> nftTransferQuery(GalaxyNftTransferQueryReqDto reqDto) {
        GalaxyTransferNftInfoBo transferNftInfoBo = dataUtils.getGalaxyTransferNftInfoBo(reqDto.getRouterType(),reqDto.getTransOrderId());

        //初始化转让信息
        if(transferNftInfoBo==null||StringUtil.isEmpty(transferNftInfoBo.getNftTransferTaskId())){
            return ResponseDto.failure(GalaxyErrorEnum.NFT_TRANSFER_QUERY_ERROR.getCode(),GalaxyErrorEnum.NFT_TRANSFER_QUERY_ERROR.getMessage());
        }
        //获取用户信息
        GalaxyUserInfoBo userInfoBo = dataUtils.getGalaxyUserInfo(reqDto.getRouterType(),transferNftInfoBo.getUserId());
        if(StringUtil.isNull(userInfoBo)){
            log.error("开始执行 nftTransfer nft owner not exist error msg:{}",GalaxyErrorEnum.NFT_TRANSFER_FAIL_OWNER_NOT_EXIST.getMessage());
            return ResponseDto.failure(GalaxyErrorEnum.NFT_TRANSFER_FAIL_OWNER_NOT_EXIST.getCode(), GalaxyErrorEnum.NFT_TRANSFER_FAIL_OWNER_NOT_EXIST.getMessage());
        }

        if(transferNftInfoBo.getTransferStatus().equalsIgnoreCase(GalaxyEnum.NftTransferStatusEnum.SUCCESS.getCode())){
            GalaxyNftTransferQueryRespDto nftTransferQueryRespDto = galaxyBeanTransferBiz.buildNftTransferQueryRespDto(transferNftInfoBo);
            nftTransferQueryRespDto.setTransferStatus(GalaxyEnum.NftTransferStatusEnum.SUCCESS.getCode());
            return ResponseDto.success(nftTransferQueryRespDto);
        }else if(transferNftInfoBo.getTransferStatus().equalsIgnoreCase(GalaxyEnum.NftTransferStatusEnum.PROCESSING.getCode())){
            //获取用户信息
            GalaxyUserInfoBo receiveUserInfoBo = dataUtils.getGalaxyUserInfo(reqDto.getRouterType(),transferNftInfoBo.getReceiveUserId());
            if(StringUtil.isNull(receiveUserInfoBo)){
                log.error("开始执行 nftTransfer nft receiver not exist error msg:{}",GalaxyErrorEnum.NFT_TRANSFER_FAIL_RECEIVER_NOT_EXIST.getMessage());
                return ResponseDto.failure(GalaxyErrorEnum.NFT_TRANSFER_FAIL_RECEIVER_NOT_EXIST.getCode(), GalaxyErrorEnum.NFT_TRANSFER_FAIL_RECEIVER_NOT_EXIST.getMessage());
            }
            //链上查询转让结果
            Nft049TransferResultReqDto nft049TransferResultReqDto = Nft049TransferResultReqDto.getNew();
            nft049TransferResultReqDto.setOperatorPubKey(userInfoBo.getUserPubKey());
            nft049TransferResultReqDto.setTaskId(transferNftInfoBo.getNftTransferTaskId());
            ZxlnftResponseDto<Nft049TransferResultRespDto> nft049ZxlnftRespDto = zxlnftSdkUtil.nft049TransferResult(nft049TransferResultReqDto);
            if(!nft049ZxlnftRespDto.isSuccess()){
                throw new ZxlNftException(ZxlErrorEnum.SYSTEM_ERROR.getCode(),ZxlErrorEnum.SYSTEM_ERROR.getMsg());
            }
            Long nftTransferChainTimestamp = null;
            Integer nftTransferStatus = null;
            String nftTransferTradeHash = null;
            GalaxyNftTransferQueryRespDto nftTransferQueryRespDto = galaxyBeanTransferBiz.buildNftTransferQueryRespDto(transferNftInfoBo);
            if (nft049ZxlnftRespDto.getData().getTaskStatus().toString().equals(ZxlnftEnum.TaskStatusEnum.TASK_SUCCESS.getCode())) {
                nftTransferChainTimestamp = nft049ZxlnftRespDto.getData().getChainTimestamp();
                nftTransferStatus = nft049ZxlnftRespDto.getData().getTaskStatus();
                nftTransferTradeHash = nft049ZxlnftRespDto.getData().getTxHash();
                if(StringUtil.isNotEmpty(nft049ZxlnftRespDto.getData().getTxHash())){
                    //更新转让成功信息
                    transferNftInfoBo.setOwnerUserId(transferNftInfoBo.getReceiveUserId());
                    transferNftInfoBo.setOwnerAddress(transferNftInfoBo.getReceiveAddress());
                    transferNftInfoBo.setTransferStatus(GalaxyEnum.NftTransferStatusEnum.SUCCESS.getCode());
                    transferNftInfoBo.setTransferHash(nftTransferTradeHash);
                    transferNftInfoBo.setUpdatedAt(DateUtil.getNowTime());
                    dataUtils.updateTransferNftInfoBo(reqDto.getRouterType(),reqDto.getTransOrderId(),transferNftInfoBo);

                    nftTransferQueryRespDto.setOwnerUserId(transferNftInfoBo.getReceiveUserId());
                    nftTransferQueryRespDto.setOwnerAddress(transferNftInfoBo.getReceiveAddress());
                    nftTransferQueryRespDto.setTransferStatus(GalaxyEnum.NftTransferStatusEnum.SUCCESS.getCode());
                    nftTransferQueryRespDto.setTransferHash(nftTransferTradeHash);
                }else{
                    nftTransferQueryRespDto.setTransferStatus(GalaxyEnum.NftTransferStatusEnum.PROCESSING.getCode());
                }
            }



            return ResponseDto.success(nftTransferQueryRespDto);
        }else {
            return ResponseDto.failure(GalaxyErrorEnum.NFT_TRANSFER_QUERY_ERROR.getCode(),GalaxyErrorEnum.NFT_TRANSFER_QUERY_ERROR.getMessage());
        }
    }

    /**
     * 核对nft当前拥有者是否匹配
     * @param userInfoBo
     * @param nftId
     * @return
     */
    private Boolean checkNftOwner(GalaxyUserInfoBo userInfoBo,String nftId){
        Boolean checkNftOwner = false;
        Nft036InfoReqDto reqDto = Nft036InfoReqDto.getNew();
        reqDto.setNftId(nftId);
        ZxlnftResponseDto<Nft036InfoRespDto> resp = zxlnftSdkUtil.nft036Info(reqDto);

        Nft036InfoRespDto nft036InfoRespDto = null;
        if(resp.isSuccess()){
            nft036InfoRespDto = resp.getParseData(Nft036InfoRespDto.class);

            String ownerAddress = nft036InfoRespDto.getNftInfo().getOwnerAddr();
            //已上链
            if(ownerAddress.equalsIgnoreCase(userInfoBo.getBlockChainAddress())){
                checkNftOwner = true;
            }
        }else{
            log.error("nftTransfer error : nftId:{} not exits on xuper blockchain :{} ",nftId,JsonUtils.toJson(nft036InfoRespDto));
        }
        return checkNftOwner;
    }
}
