package com.fzm.mall.server.admin.goods_center.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fzm.mall.server.admin.goods_center.entity.dto.ExternalTokenDTO;
import com.fzm.mall.server.admin.goods_center.entity.vo.ExternNFTVO;
import com.fzm.mall.server.admin.goods_center.entity.vo.ExternalTokenListVO;
import com.fzm.mall.server.admin.goods_center.entity.vo.ExternalTokenVO;
import com.fzm.mall.server.admin.goods_center.model.ExternalToken;
import com.fzm.mall.server.admin.goods_center.mapper.ExternalTokenMapper;
import com.fzm.mall.server.admin.goods_center.model.GoodsNft;
import com.fzm.mall.server.admin.goods_center.model.Sku;
import com.fzm.mall.server.admin.goods_center.service.IExternalTokenService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fzm.mall.server.admin.goods_center.service.IGoodsNftService;
import com.fzm.mall.server.admin.goods_center.service.ISkuService;
import com.fzm.mall.server.admin.home_page.dao.MerchantMapper;
import com.fzm.mall.server.admin.util.HttpUtil;
import com.fzm.mall.server.admin.util.UUIDUtil;
import org.dozer.DozerBeanMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 外部商品通证 服务实现类
 * </p>
 *
 * @author fzm
 * @since 2021-08-10
 */
@Service
@Transactional
public class ExternalTokenServiceImpl extends ServiceImpl<ExternalTokenMapper, ExternalToken> implements IExternalTokenService {

    @Autowired
    private ExternalTokenMapper externalTokenMapper;
    @Autowired
    private MerchantMapper merchantMapper;
    @Autowired
    private DozerBeanMapper beanMapper;
    @Autowired
    private IGoodsNftService goodsNftService;
    @Autowired
    private ISkuService skuService;
    @Value("${ly.url}")
    private String url;

    @Override
    public IPage<ExternalTokenDTO> page(Page<ExternalTokenDTO> page, String labelName, String goodsId, String goodsName,
                                        Integer status, String merchantId) {
        return externalTokenMapper.page(page, labelName, goodsId, goodsName, status, merchantId);
    }

    @Override
    public ExternalTokenVO read(String merchantId) {
        return merchantMapper.read(merchantId);
    }

    @Override
    public List<ExternalTokenListVO> unbindToken(String merchantId) {
        LambdaQueryWrapper<ExternalToken> qw = new LambdaQueryWrapper<>();
        qw.eq(ExternalToken::getMerchantId, merchantId);
        qw.eq(ExternalToken::getStatus, ExternalToken.UNBIND);
        qw.ne(ExternalToken::getType, 3);
        qw.orderByDesc(ExternalToken::getCreateTime);
        return list(qw).stream().map(v -> beanMapper.map(v, ExternalTokenListVO.class)).collect(Collectors.toList());
    }

    @Override
    public void addToken(String merchantId, String coin, Long tokenId, Integer goodsType, String name, BigDecimal amount, Integer type, Long publishTime, String publisher) {
        ExternalToken token = queryByLabelNameAndMerchantId(coin, merchantId);

        if (token != null) {
            token.setAvailableNumber(token.getAvailableNumber().add(amount));
            if (token.getStatus().equals(1)) {
                token.setBindNumber(token.getAvailableNumber().add(amount));
            }
            updateById(token);
            if (type.equals(3)) {
                GoodsNft goodsNft = goodsNftService.queryByTokenId(coin);
                if (goodsNft != null) {
                    goodsNft.setNumber(goodsNft.getNumber() + amount.longValue());
                    goodsNftService.updateById(goodsNft);
                    boolean update = false;
                    while (!update) {
                        Sku sku = skuService.getByCoin(coin);
                        LambdaUpdateWrapper<Sku> uw = new LambdaUpdateWrapper<>();
                        uw.set(Sku::getStock, sku.getStock() + amount.longValue());
                        uw.set(Sku::getCirculation, token.getAvailableNumber().add(amount).longValue());
                        uw.eq(Sku::getUpdateTime, sku.getUpdateTime());
                        update = skuService.update(uw);
                    }
                }
            }
        } else {
            ExternalToken externalToken = new ExternalToken();
            externalToken.setCommodityPassId(UUIDUtil.getUUID());
            externalToken.setLabelName(coin);
            externalToken.setAvailableNumber(amount);
            externalToken.setMerchantId(merchantId);
            externalToken.setType(type);
            externalToken.setTokenId(tokenId);
            externalToken.setGoodsType(goodsType);
            externalToken.setName(name);
            externalToken.setPublishTime(publishTime);
            externalToken.setPublisher(publisher);

            if (!url.equals("http://146.56.218.121:8081/open/nft/hash")) {
                Map<String, Object> map = new HashMap<>();
                map.put("tokenId", tokenId);
                String httpGet = HttpUtil.httpGet(url, map);
                JSONObject json = JSONObject.parseObject(httpGet);
                if (json.getString("code").equals("200")) {
                    externalToken.setHash(json.getString("data"));
                }
            }
            //TODO 唐拓接口
            save(externalToken);
        }
    }

    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<>();
        map.put("tokenId", 1475715277122572288L);
        String httpGet = HttpUtil.httpGet("http://146.56.218.121:12100/open/nft/hash", map);
        JSONObject json = JSONObject.parseObject(httpGet);
        if (json.getString("code").equals("200")) {
            System.err.println(json.getString("data"));
        }
    }


    @Override
    public ExternalToken queryByLabelNameAndMerchantId(String coin, String merchantId) {
        LambdaQueryWrapper<ExternalToken> qw = new LambdaQueryWrapper<>();
        qw.eq(ExternalToken::getLabelName, coin);
        qw.eq(ExternalToken::getMerchantId, merchantId);
        return getOne(qw);
    }

    @Override
    public List<ExternNFTVO> queryByMerchantId(String merchantId) {
        LambdaQueryWrapper<ExternalToken> qw = new LambdaQueryWrapper<>();
        qw.eq(ExternalToken::getMerchantId, merchantId);
        qw.eq(ExternalToken::getStatus, ExternalToken.UNBIND);
        qw.eq(ExternalToken::getType, 3);
        qw.orderByDesc(ExternalToken::getCreateTime);
        return list(qw).stream().map(v -> beanMapper.map(v, ExternNFTVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public ExternalToken queryByComId(String comId) {
        LambdaQueryWrapper<ExternalToken> qw = new LambdaQueryWrapper<>();
        qw.eq(ExternalToken::getCommodityPassId, comId);
        return getOne(qw);
    }
}

