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

import com.liquidnet.common.exception.constant.ErrorCode;
import com.liquidnet.common.third.xuper.config.XuperConfig;
import com.liquidnet.common.third.xuper.dto.*;
import com.liquidnet.common.third.xuper.exception.XupterException;
import com.liquidnet.common.third.xuper.util.XuperSdkUtil;
import com.liquidnet.common.third.zxlnft.dto.Nft044BuyResultReqDto;
import com.liquidnet.commons.lang.util.BeanUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.commons.lang.util.StringUtil;
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.GalaxyNftOrderBindBo;
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.dto.vo.mongo.GalaxyNftOrderFailLogVo;
import com.liquidnet.service.galaxy.exception.GalaxyNftBuyException;
import com.liquidnet.service.galaxy.utils.GalaxyDataUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Date;

/**
 * @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/6/27 13:08
 */
@Slf4j
@Component
public class XuperTradeCommonBiz {
    @Autowired
    private XuperSdkUtil xuperSdkUtil;

    @Autowired
    private XuperConfig xuperConfig;

    @Autowired
    private GalaxyDataUtils dataUtils;

    @Autowired
    private GalaxyBeanTransferBiz galaxyBeanTransferBiz;

    public GalaxyNftPublishAndBuyRespDto executeBuyBusiness(GalaxyNftPublishAndBuyReqDto reqDto,GalaxyUserInfoBo userInfoBo, GalaxySeriesNftInfoBo seriesNftInfoBo,GalaxyNftOrderBo nftOrderBo){
        String buyFailDesc = null;
        //执行购买逻辑
        GalaxyNftPublishAndBuyRespDto nftPublishAndBuyRespDto = GalaxyNftPublishAndBuyRespDto.getNew();
        try{
            GalaxyNftBuyRespDto nftBuyRespDto = this.nftBuyBusinessSync(reqDto.getRouterType(),nftOrderBo.getNftId(),userInfoBo,seriesNftInfoBo,nftOrderBo);
            BeanUtil.copy(nftBuyRespDto,nftPublishAndBuyRespDto);
        }catch (GalaxyNftBuyException e){
            buyFailDesc = e.getMessage();
        }catch(Exception e){
            buyFailDesc = e.getMessage();
            log.error(e.getMessage(),e);
        }

        if(StringUtil.isNotEmpty(buyFailDesc)){
            //记录购买异常信息
            try{
                GalaxyNftOrderFailLogVo nftOrderFailLogVo = galaxyBeanTransferBiz.buildNftOrderFailLogVo(GalaxyEnum.TradeTypeEnum.TRADE_BUY,reqDto,GalaxyEnum.OrderDealWithStatusEnum.DATA_INIT,buyFailDesc,null
                        ,userInfoBo,seriesNftInfoBo,nftOrderBo);
                dataUtils.setNftOrderFailLogVo(reqDto.getRouterType(),nftOrderFailLogVo);
            }catch(Exception e){
                log.error(reqDto.getNftOrderPayId()+"购买setNftOrderFailLogVo记录异常："+e.getMessage(),e);
            }
        }
        return nftPublishAndBuyRespDto;
    }

    /**
     * 保持线程循环查询
     * @param nftId
     * @param userInfoBo
     * @param seriesNftInfoBo
     * @return
     */
    private GalaxyNftBuyRespDto nftBuyBusinessSync(String routerType,String nftId,GalaxyUserInfoBo userInfoBo, GalaxySeriesNftInfoBo seriesNftInfoBo,GalaxyNftOrderBo nftOrderBo){
        //定义返回参数
        String nftBuyTaskId = null;
        String nftBuyChainTimestamp = null;
        Integer nftBuyStatus = null;
        String nftBuyTradeHash = null;
        String nftBuyPayTaskId = null;

        /**
         * 获取订单和nft绑定信息
         */
        Long shardId = -1l;
        GalaxyNftOrderBindBo nftOrderBindBo = dataUtils.getGalaxyNftOrderBindBo(routerType,nftOrderBo.getNftOrderPayId());
        if(StringUtil.isNotNull(nftOrderBindBo)){
            shardId = nftOrderBindBo.getNftIdIndex().longValue();
        }


        //如果购买任务不为空，则直接进行购买任务查询
        if(StringUtil.isNotEmpty(nftOrderBo.getNftBuyTaskId())){
            nftBuyTaskId = nftOrderBo.getNftBuyTaskId();
        }

        if(StringUtil.isEmpty(nftBuyTaskId)){
            //购买
            Xuper007GrantShardReqDto xuper007GrantShardReqDto = Xuper007GrantShardReqDto.getNew();
            // 定义返回结果对象
            Xuper007GrantShardRespDto xuper007GrantShardRespDto = null;
            long assetId = Long.parseLong(seriesNftInfoBo.getSeriesId());
            try {
                xuper007GrantShardReqDto.setMnemonic(xuperConfig.getNftPlatformMnemonic());
                xuper007GrantShardReqDto.setAssetId(assetId);
                xuper007GrantShardReqDto.setShardId(shardId);
                xuper007GrantShardReqDto.setToAddr(xuperSdkUtil.getAccount(userInfoBo.getMnemonic()).getAddress());
                xuper007GrantShardReqDto.setToUserId(100000l);
                xuper007GrantShardReqDto.setPrice(seriesNftInfoBo.getSellCount().longValue());
                XuperResponseDto<Xuper007GrantShardRespDto> xuperResponseDto = xuperSdkUtil.xuper007GrantShard(xuper007GrantShardReqDto);
                if(xuperResponseDto.isSuccess()){
                    xuper007GrantShardRespDto = xuperResponseDto.getParseData(Xuper007GrantShardRespDto.class);
                }
            }catch (XupterException e) {
                log.error("biz error msg "+e.getMessage(),e);
            }catch (Exception e) {
                log.error("sys error msg "+e.getMessage(),e);
            }
            log.info("testXuper007GrantShard resp : "+ JsonUtils.toJson(xuper007GrantShardRespDto));
            if(StringUtil.isNotNull(xuper007GrantShardRespDto)&&xuper007GrantShardRespDto.getErrNo()==0){
                nftBuyTaskId = String.valueOf(assetId);
                nftOrderBo.setNftBuyTaskId(nftBuyTaskId);
            }
        }

        //如果购买任务id不为空
        if(StringUtil.isNotEmpty(nftBuyTaskId)){
            try{
                //3.2.4查询NFT购买结果
                Nft044BuyResultReqDto nft044ReqDto = Nft044BuyResultReqDto.getNew();
                nft044ReqDto.setTaskId(nftBuyTaskId);

                long timeStart = System.currentTimeMillis();

                int count  = 0;
                while(nftBuyPayTaskId == null){
                    Thread.sleep(500l);
                    count++;
                    log.info("=======执行nft购买第{}次查询,taskId:{}",count,nft044ReqDto.getTaskId());
                    //执行nft购买结果查询
                    GalaxyNftBuyResultQueryReqDto nftBuyResultQueryReqDto = GalaxyNftBuyResultQueryReqDto.getNew();
                    nftBuyResultQueryReqDto.setNftOrderPayId(nftOrderBo.getNftOrderPayId());
                    nftBuyResultQueryReqDto.setRouterType(routerType);
                    ResponseDto<GalaxyNftBuyResultQueryRespDto> buyResultQueryRespDto= this.nftBuyResultQuery(nftBuyResultQueryReqDto,nftOrderBo);
                    if(buyResultQueryRespDto.isSuccess()){
                        if(buyResultQueryRespDto.getData().getTaskStatus().toString().equals(GalaxyEnum.TaskStatusEnum.TASK_SUCCESS.getCode())){
                            nftBuyPayTaskId = buyResultQueryRespDto.getData().getPayTaskId();
                            nftBuyChainTimestamp = buyResultQueryRespDto.getData().getChainTimestamp();
                            nftBuyStatus = buyResultQueryRespDto.getData().getTaskStatus();
                            nftBuyTradeHash = buyResultQueryRespDto.getData().getTxHash();
                        }else if(buyResultQueryRespDto.getData().getTaskStatus().toString().equals(GalaxyEnum.TaskStatusEnum.TASK_FAIL.getCode())){
                            log.info("任务执行失败！taskId:{}",nft044ReqDto.getTaskId());
                            nftBuyStatus = buyResultQueryRespDto.getData().getTaskStatus();
                            //购买失败
                            throw new GalaxyNftBuyException(GalaxyErrorEnum.NFT_BUY_FAIL.getCode(), "nftBuyResultQuery:"+GalaxyErrorEnum.NFT_BUY_FAIL.getMessage());
                        }else if(buyResultQueryRespDto.getData().getTaskStatus().toString().equals(GalaxyEnum.TaskStatusEnum.PROCESSING.getCode())){
                            log.info("任务执行中！taskId:{}",nft044ReqDto.getTaskId());
                            nftBuyStatus = buyResultQueryRespDto.getData().getTaskStatus();
                        }
                    }

                    if(count==20){
                        //查询超过20次，则把nftId设置为空，为后续重新入队
                        nftId = null;
                        log.info("=======查询共20次，跳出循环！taskId:{}",nft044ReqDto.getTaskId());
                        break;
                    }
                }
                log.info("总共执行了多少次查询：{} 总耗时:{}",count,System.currentTimeMillis() - timeStart);
            }catch (GalaxyNftBuyException e){
                throw new GalaxyNftBuyException(e.getCode(),e.getMessage());
            }catch(Exception e){
                log.error(e.getMessage(),e);
                //发行失败
                throw new GalaxyNftBuyException(GalaxyErrorEnum.NFT_BUY_ERROR.getCode(),"nftBuyResultQuery_exception:"+e.getMessage());
            }

            //更新订单缓存数据状态
            if(StringUtil.isNotNull(nftBuyChainTimestamp)){
                //设置时间
                String nftBuyChainTimestampStr = DateUtil.format(new Date(),DateUtil.Formatter.yyyyMMddHHmmss);
                nftOrderBo.setNftBuyChainTimestamp(nftBuyChainTimestampStr);
            }
            if(StringUtil.isNotNull(nftBuyStatus)){
                nftOrderBo.setNftBuyStatus(nftBuyStatus.toString());
            }
            nftOrderBo.setNftBuyTradeHash(nftBuyTradeHash);
            nftOrderBo.setNftBuyPayTaskId(nftBuyPayTaskId);
            nftOrderBo.setUpdatedAt(LocalDateTime.now());
            //先更新nft购买数据
            dataUtils.updateNftOrderBuyInfo(routerType,nftOrderBo.getNftOrderPayId(),nftOrderBo);
        }else{
            //购买失败
            throw new GalaxyNftBuyException(GalaxyErrorEnum.NFT_BUY_ERROR.getCode(),"nftBuyResultQuery: nftBuyTaskId："+nftBuyTaskId);
        }

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

    public ResponseDto<GalaxyNftBuyResultQueryRespDto> nftBuyResultQuery(GalaxyNftBuyResultQueryReqDto reqDto,GalaxyNftOrderBo nftOrderBo) {
        //获取订单信息
//        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());
        }
        //执行资产碎片授予查询
        Xuper010QuerySdsReqDto xuper010QuerySdsReqDto = Xuper010QuerySdsReqDto.getNew();
        // 定义返回结果对象
        Xuper010QuerySdsRespDto xuper010QuerySdsRespDto = null;
        long shardId = 1l;
        try {
            xuper010QuerySdsReqDto.setAssetId(Long.parseLong(nftOrderBo.getSeriesId()));
            xuper010QuerySdsReqDto.setShardId(shardId);
            XuperResponseDto<Xuper010QuerySdsRespDto>  xuperResponseDto = xuperSdkUtil.xuper010QuerySds(xuper010QuerySdsReqDto);
            if(xuperResponseDto.isSuccess()){
                xuper010QuerySdsRespDto = xuperResponseDto.getParseData(Xuper010QuerySdsRespDto.class);
            }
        }catch (XupterException e) {
            log.error("biz error msg "+e.getMessage(),e);
        }catch (Exception e) {
            log.error("sys error msg "+e.getMessage(),e);
        }
        log.info("xuper010QuerySds resp : "+ JsonUtils.toJson(xuper010QuerySdsRespDto));

        if(String.valueOf(xuper010QuerySdsRespDto.getErrNo()).equalsIgnoreCase(ErrorCode.SUCCESS.getCode())){
            GalaxyNftBuyResultQueryRespDto resultQueryRespDto = GalaxyNftBuyResultQueryRespDto.getNew();
            String nowTimeStr = DateUtil.getNowTime();
            //转换任务状态
            Integer taskStatus = Integer.valueOf(GalaxyEnumBiz.getGrantStatusEnum(reqDto.getRouterType(),String.valueOf(xuper010QuerySdsRespDto.getMeta().getStatus())).getCode());
            resultQueryRespDto.setTaskStatus(taskStatus);
            resultQueryRespDto.setChainTimestamp(nowTimeStr);
            resultQueryRespDto.setPayTaskId(xuper010QuerySdsRespDto.getMeta().getTxId());
            resultQueryRespDto.setTxHash(xuper010QuerySdsRespDto.getMeta().getTxId());
            return ResponseDto.success(resultQueryRespDto);
        }else{
            return ResponseDto.failure(GalaxyErrorEnum.NFT_PUBLISH_AND_BUY_QUERY_FAIL.getCode(),GalaxyErrorEnum.NFT_PUBLISH_AND_BUY_QUERY_FAIL.getMessage());
        }
    }
}
