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.dto.*;
import com.liquidnet.common.third.zxlnft.util.ZxlnftSdkUtil;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.constant.MQConst;
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.GalaxyUserInfoBo;
import com.liquidnet.service.galaxy.dto.param.*;
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.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();
        BeanUtil.copy(nft044RespDto.getData(),resultQueryRespDto);
        String nowTimeStr = DateUtil.format(new Date(nft044RespDto.getData().getChainTimestamp().longValue()*1000),DateUtil.Formatter.yyyyMMddHHmmss);
        //转换任务状态
        Integer taskStatus = Integer.valueOf(GalaxyEnumBiz.getTaskStatusEnum(reqDto.getRouterType(),nft044RespDto.getData().getTaskStatus().toString()).getCode());
        resultQueryRespDto.setTaskStatus(taskStatus);
        resultQueryRespDto.setChainTimestamp(nowTimeStr);
        return ResponseDto.success(resultQueryRespDto);
    }

    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);
            if(publishResultQueryRespDto.isSuccess()){
                GalaxyNftPublishResultQueryRespDto nftPublishResultQueryRespDtoTemp = publishResultQueryRespDto.getData();
                BeanUtil.copy(nftPublishResultQueryRespDtoTemp,nftOrderBo);
            }
        }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(buyResultQueryRespDto.isSuccess()){
                GalaxyNftBuyResultQueryRespDto nftBuyResultQueryRespDtoTemp = buyResultQueryRespDto.getData();
                BeanUtil.copy(nftBuyResultQueryRespDtoTemp,nftOrderBo);
            }
        }

        //判断是否需要二次购买
        if(isNeedSecondBuy){
            queueUtil.sendMsgByRedis(MQConst.GalaxyQueue.JSON_NFT_PUBLISH_AND_BUY.getKey(), JsonUtils.toJson(reqDto));
        }

        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);
    }
}
