package com.liquidnet.service.goblin.service.impl;

import com.liquidnet.service.base.PagedResult;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.dto.GoblinQueueBizArtworkGenDto;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.service.IGoblinUserDigitalArtworkService;
import com.liquidnet.service.goblin.service.impl.inner.GoblinGalaxyService;
import com.liquidnet.service.goblin.util.GoblinMongoUtils;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.ObjectUtil;
import com.liquidnet.service.goblin.util.QueueUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class GoblinUserDigitalArtworkServiceImpl implements IGoblinUserDigitalArtworkService {
    @Autowired
    private QueueUtils queueUtils;
    @Autowired
    private GoblinRedisUtils goblinRedisUtils;
    @Autowired
    private GoblinMongoUtils goblinMongoUtils;
    @Autowired
    private GoblinGalaxyService goblinGalaxyService;

    @Override
    public GoblinUserDigitalArtworkPageVo page(String uid, Integer pageNum, Integer pageSize) {
        GoblinUserDigitalArtworkPageVo pageVo = GoblinUserDigitalArtworkPageVo.getNew();
        long artworkNum = goblinRedisUtils.countUserDigitalArtwork(uid);
        if (artworkNum > 0) {
            if (artworkNum > 30 && pageNum * pageSize > 30) {// 查询Mongo
                if ((long) pageNum * pageSize > artworkNum) pageNum = Math.toIntExact(artworkNum / pageSize);
                PagedResult<GoblinUserDigitalArtworkListVo> listVoPagedResult = goblinMongoUtils.getUserDigitalArtworkListVos(uid, pageNum, pageSize);
                listVoPagedResult.setTotal(artworkNum, pageSize);
                pageVo.setArtworkNum((int) artworkNum).setPagedResult(listVoPagedResult).setSystime(LocalDateTime.now());
            } else {
                PagedResult<GoblinUserDigitalArtworkListVo> listVoPagedResult = ObjectUtil.getGoblinUserDigitalArtworkListVoPagedResult();
                List<GoblinUserDigitalArtworkListVo> list = ObjectUtil.getGoblinUserDigitalArtworkListVoArrayList();

                List<String> userDigitalArtworkIds = goblinRedisUtils.getUserDigitalArtworkIds(uid);
                if (CollectionUtils.isEmpty(userDigitalArtworkIds)) {
                    log.warn("#我的藏品列表:藏品IDS缓存为空[uid={},artworkNum={}]", uid, artworkNum);
                    return pageVo.setArtworkNum((int) artworkNum).setPagedResult(listVoPagedResult).setSystime(LocalDateTime.now());
                }
                int cacheSize = userDigitalArtworkIds.size(), cacheNum = cacheSize / pageSize;// 分几页
                int fromIndex = Math.min(Math.min(cacheNum, pageNum - 1) * pageSize, cacheSize - 1);
                List<String> subList = userDigitalArtworkIds.subList(fromIndex, Math.min(fromIndex + pageSize, cacheSize));

                LocalDateTime now = LocalDateTime.now(), toCheckTime = now.minusSeconds(15);
                for (int i = 0, subSize = subList.size(); i < subSize; i++) {
                    GoblinUserDigitalArtworkVo userDigitalArtworkVo = goblinRedisUtils.getUserDigitalArtworkVo(subList.get(i));
                    if (null != userDigitalArtworkVo) {
                        GoblinGoodsSkuInfoVo goodsSkuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(userDigitalArtworkVo.getSkuId());

                        GoblinUserDigitalArtworkListVo listVo = GoblinUserDigitalArtworkListVo.getNew().copy(userDigitalArtworkVo);
                        listVo.setName(goodsSkuInfoVo.getName());
                        listVo.setSubtitle(goodsSkuInfoVo.getSubtitle());
                        listVo.setCoverPic(goodsSkuInfoVo.getSkuPic());
                        listVo.setEdition(goodsSkuInfoVo.getSkuStock());
                        listVo.setUnbox(goodsSkuInfoVo.getUnbox());
                        listVo.setOpeningTime(goodsSkuInfoVo.getOpeningTime());

                        if ("0".equals(listVo.getUnbox()) && 1 != listVo.getState() && listVo.getCreatedAt().isBefore(toCheckTime)) {// 15秒前创建的藏品，去主动核实发行交易状态
                            List<String> checkRespDataList = goblinGalaxyService.checkNftTradeResult(uid, userDigitalArtworkVo.getOrderId(), goodsSkuInfoVo.getRouteType());
                            this.updateUserDigitalArtworkByChainTrade(userDigitalArtworkVo, listVo, checkRespDataList, now);
                        } else if (1 == listVo.getState() && "1".equals(listVo.getUnbox())) {// 盲盒已开启的，直接展示开出的藏品封面
                            GoblinNftOrderVo goblinNftOrder = goblinRedisUtils.getGoblinNftOrder(userDigitalArtworkVo.getOrderId());
                            goodsSkuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(goblinNftOrder.getBoxSkuId());
                            listVo.setCoverPic(goodsSkuInfoVo.getSkuPic());
                        }

                        list.add(listVo);
                    }
                }

                listVoPagedResult.setList(list).setTotal(artworkNum, pageSize);
                pageVo.setArtworkNum((int) artworkNum).setPagedResult(listVoPagedResult).setSystime(LocalDateTime.now());
            }
        }
        return pageVo;
    }

    @Override
    public GoblinUserDigitalArtworkInfoVo info(String uid, String artworkId) {
        GoblinUserDigitalArtworkVo userDigitalArtworkVo = goblinRedisUtils.getUserDigitalArtworkVo(artworkId);
        if (null != userDigitalArtworkVo && userDigitalArtworkVo.getUid().equals(uid)) {
            GoblinUserDigitalArtworkInfoVo artworkInfoVo = GoblinUserDigitalArtworkInfoVo.getNew().copy(userDigitalArtworkVo);

            GoblinGoodsSkuInfoVo goodsSkuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(userDigitalArtworkVo.getSkuId());
            GoblinGoodsInfoVo goodsInfoVo = goblinRedisUtils.getGoodsInfoVo(goodsSkuInfoVo.getSpuId());

            artworkInfoVo.setName(goodsSkuInfoVo.getName());
            artworkInfoVo.setSubtitle(goodsSkuInfoVo.getSubtitle());
            artworkInfoVo.setMaterialType(goodsSkuInfoVo.getMaterialType());
            artworkInfoVo.setMaterialUrl(goodsSkuInfoVo.getMaterialUrl());
            artworkInfoVo.setEdition(goodsSkuInfoVo.getSkuStock());
            artworkInfoVo.setAuthor(goodsInfoVo.getAuthor());
            artworkInfoVo.setPublisher(goodsInfoVo.getPublisher());
            artworkInfoVo.setDetails(goodsSkuInfoVo.getDetails());

            return artworkInfoVo;
        }
        return null;
    }

    @Override
    public GoblinUserDigitalArtworkListVo unboxingForBuyOrExchange(String uid, GoblinUserDigitalArtworkVo userDigitalArtworkVo) {
        String orderId = userDigitalArtworkVo.getOrderId();
        GoblinNftOrderVo goblinNftOrder = goblinRedisUtils.getGoblinNftOrder(orderId);
        GoblinGoodsSkuInfoVo unboxSkuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(goblinNftOrder.getBoxSkuId());

        GoblinUserDigitalArtworkListVo unboxDigitalArtworkListVo = GoblinUserDigitalArtworkListVo.getNew();
//        unboxDigitalArtworkListVo.setArtworkId();
        unboxDigitalArtworkListVo.setName(unboxSkuInfoVo.getName());
        unboxDigitalArtworkListVo.setSubtitle(unboxSkuInfoVo.getSubtitle());
        unboxDigitalArtworkListVo.setCoverPic(unboxSkuInfoVo.getSkuPic());
//        unboxDigitalArtworkListVo.setSource(userDigitalArtworkVo.getSource());
//        unboxDigitalArtworkListVo.setState(0);
//        unboxDigitalArtworkListVo.setCreatedAt();
//        unboxDigitalArtworkListVo.setUnbox("0");
//        unboxDigitalArtworkListVo.setOpeningTime(now);

        LocalDateTime now = LocalDateTime.now();
        userDigitalArtworkVo.setState(1);
        userDigitalArtworkVo.setDelFlg("1");// 盲盒开启后直接删除
        userDigitalArtworkVo.setOpeningAt(now);
        userDigitalArtworkVo.setUpdatedAt(now);
        userDigitalArtworkVo.setDeletedAt(now);

//        if (goblinMongoUtils.updateUserDigitalArtworkVoByUnboxing(userDigitalArtworkVo)) {
            goblinRedisUtils.setexUserDigitalArtworkVo(userDigitalArtworkVo);

            String artworkId = userDigitalArtworkVo.getArtworkId();
            GoblinQueueBizArtworkGenDto queueBizArtworkGenDto = GoblinQueueBizArtworkGenDto.getNew();
            queueBizArtworkGenDto.setUid(uid);
            queueBizArtworkGenDto.setSkuId(unboxSkuInfoVo.getSkuId());
            queueBizArtworkGenDto.setOrderId(orderId);
            queueBizArtworkGenDto.setSource(userDigitalArtworkVo.getSource());
            queueBizArtworkGenDto.setFromArtId(artworkId);
            queueUtils.sendMsgByRedis(MQConst.GoblinQueue.BIZ_ARTWORK_GEN.getKey(), queueBizArtworkGenDto.toJson());
            queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_ARTWORK_GEN.getKey(),
                    SqlMapping.get("goblin_user_digital_artwork.update_for_unboxing", now, now, now, artworkId));
//        }
        return unboxDigitalArtworkListVo;
    }

    /* -------------------------------------------------------------------------------------------------------------- */
    /* -------------------------------------------------------------------------------------------------------------- */
    /* -------------------------------------------------------------------------------------------------------------- */

    private void updateUserDigitalArtworkByChainTrade(GoblinUserDigitalArtworkVo userDigitalArtworkVo, GoblinUserDigitalArtworkListVo listVo,
                                                      List<String> checkRespDataList, LocalDateTime now) {
        if (!CollectionUtils.isEmpty(checkRespDataList)) {
            String nftId = checkRespDataList.get(0);
            String nftPublishChainTimestamp = checkRespDataList.get(1);
            String nftPublishTxHash = checkRespDataList.get(2);
            String nftBuyChainTimestamp = checkRespDataList.get(3);
            String nftBuyTxHash = checkRespDataList.get(4);

            listVo.setState(1);
            listVo.setEditionSn(Integer.valueOf(nftId.substring(nftId.indexOf("_") + 1)));

            userDigitalArtworkVo.setEditionSn(listVo.getEditionSn());
            userDigitalArtworkVo.setNftId(nftId);
            userDigitalArtworkVo.setReleaseAt(nftPublishChainTimestamp);
            userDigitalArtworkVo.setReleaseTxhash(nftPublishTxHash);
            userDigitalArtworkVo.setTradingAt(nftBuyChainTimestamp);
            userDigitalArtworkVo.setTradingTxhash(nftBuyTxHash);
            userDigitalArtworkVo.setState(1);
            userDigitalArtworkVo.setUpdatedAt(now);

            goblinRedisUtils.setUserDigitalArtworkVo(userDigitalArtworkVo);
            goblinMongoUtils.updateUserDigitalArtworkVoByChainTrade(userDigitalArtworkVo);

            queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_ARTWORK_GEN.getKey(),
                    SqlMapping.get("goblin_user_digital_artwork.update_for_chain",
                            userDigitalArtworkVo.getEditionSn(), userDigitalArtworkVo.getNftId(), userDigitalArtworkVo.getReleaseTxhash(),
                            userDigitalArtworkVo.getReleaseAt(), userDigitalArtworkVo.getTradingTxhash(), userDigitalArtworkVo.getTradingAt(),
                            userDigitalArtworkVo.getState(), userDigitalArtworkVo.getUpdatedAt(), userDigitalArtworkVo.getArtworkId())
            );
        }
    }
}
