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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSkuInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinNftExCodeVo;
import com.liquidnet.service.goblin.dto.vo.GoblinNftExSkuVo;
import com.liquidnet.service.goblin.entity.GoblinGoodsSku;
import com.liquidnet.service.goblin.entity.GoblinNftExCode;
import com.liquidnet.service.goblin.entity.GoblinNftExSku;
import com.liquidnet.service.goblin.mapper.GoblinGoodsSkuMapper;
import com.liquidnet.service.goblin.mapper.GoblinNftExCodeMapper;
import com.liquidnet.service.goblin.mapper.GoblinNftExSkuMapper;
import com.liquidnet.service.goblin.param.GoblinNftExSkuParam;
import com.liquidnet.service.goblin.service.IGoblinNftExSkuService;
import com.liquidnet.service.platform.utils.GoblinRedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @Author: wll
 * @Description: nft兑换活动和和sku的关联
 * @Date:Create：in 2022/4/19 5:14 下午
 */

@Service
@Slf4j
public class GoblinNftExSkuServiceImpl implements IGoblinNftExSkuService {

    @Autowired
    private GoblinNftExCodeMapper goblinNftExCodeMapper;
    @Autowired
    private GoblinNftExSkuMapper goblinNftExSkuMapper;
    @Autowired
    private GoblinRedisUtils goblinRedisUtils;
    @Autowired
    private GoblinGoodsSkuMapper goblinGoodsSkuMapper;


    @Transactional
    @Override
    public Boolean add(List<GoblinNftExSkuParam> goblinNftExSkuParams) {

        LocalDateTime now = LocalDateTime.now();

/*        ArrayList<GoblinNftExSkuVo> goblinNftExSkuArrayList = ObjectUtil.getGoblinNftExSkuArrayList();
        ArrayList<GoblinNftExCodeVo> goblinNftExCodeArrayList = ObjectUtil.getGoblinNftExCodeArrayList();*/


        Boolean bol = false;
        String spuId = "";
        for (GoblinNftExSkuParam goblinNftExSkuParam : goblinNftExSkuParams) {
            if (goblinNftExSkuParam.getUnbox().equals("1")) {
                bol = true;
                spuId = goblinNftExSkuParam.getSpuId();
                break;
            }
        }


        Map<String, BigDecimal> map = new HashMap<>();
        if (bol) {
            // 获取spu下所有sku
            List<GoblinGoodsSku> goblinGoodsSkus = goblinGoodsSkuMapper.selectBySpuIds(spuId);
            for (GoblinGoodsSku goblinGoodsSku : goblinGoodsSkus) {
                if (goblinGoodsSku.getUnbox().equals("1")) {
                    continue;
                }
                // 不能购买的 没库存的 概率是0的 过滤
                if (getSkuAllStatusShow(goblinGoodsSku) && goblinRedisUtils.getSkuAllStatusStock(goblinGoodsSku) > 0 && goblinGoodsSku.getHitRatio() != null) {
                    map.put(goblinGoodsSku.getSkuId(), goblinGoodsSku.getHitRatio());
                }
            }
        }


        List<GoblinNftExSku> goblinNftExSkus = new ArrayList<>();
        List<GoblinNftExCode> goblinNftExCodes = new ArrayList<>();


        // 构建对象
        long startr = System.currentTimeMillis();

        Map<String, GoblinNftExSkuParam> goblinNftExSkuParamMap = new HashMap<>();

        for (GoblinNftExSkuParam goblinNftExSkuParam : goblinNftExSkuParams) {

            GoblinNftExSku goblinNftExSku = new GoblinNftExSku();
            BeanUtils.copyProperties(goblinNftExSkuParam, goblinNftExSku);
            goblinNftExSku.setCreatedAt(now);


            // 盲盒  概率
            switch (goblinNftExSkuParam.getUnbox()) {
                case "1":
                    // sku ---> 库存
                    Map<String, Integer> skuMap = getSkuHitRatio(goblinNftExSkuParam.getExStock(), map);
                    for (String key : skuMap.keySet()) {

                        Integer stockNum = skuMap.get(key);

                        // 根据sku减库存
                        int stock = goblinRedisUtils.decrSkuStock(null, key, stockNum);
                        if (stock < 0) {
                            goblinRedisUtils.incrSkuStock(null, key, stockNum);
                        }else {
                            for (int i = 0; i < stockNum; i++) {
                                GoblinNftExCode goblinNftExCode = GoblinNftExCode.getNew();
                                goblinNftExCode.setCodeId(IDGenerator.nextSnowId());
                                goblinNftExCode.setActivityId(goblinNftExSkuParam.getActivityId());

                                // 获取兑换码ZA
                                // 样例 2978-6496-9269-0694-XX
                                String code = IDGenerator.createCode(3, 4, true);
                                goblinNftExCode.setCode(code);
                                goblinNftExCode.setBoxSkuId(key);
                                goblinNftExCode.setState(1);
                                goblinNftExCode.setCreatedAt(now);
                                goblinNftExCodes.add(goblinNftExCode);

                                GoblinNftExCodeVo goblinNftExCodeVo = GoblinNftExCodeVo.getNew().copy(goblinNftExCode);

                                // 赋值额外属性
                                goblinNftExCodeVo.setExLimit(goblinNftExSkuParam.getExLimit());
                                goblinNftExCodeVo.setExStartTime(goblinNftExSkuParam.getExStartTime());
                                goblinNftExCodeVo.setExStopTime(goblinNftExSkuParam.getExStopTime());
                                goblinNftExCodeVo.setStoreId(goblinNftExSkuParam.getStoreId());
                                goblinNftExCodeVo.setSpuId(goblinNftExSkuParam.getSpuId());

                                // LocalDateTime exStartTime = goblinNftExSkuParam.getExStartTime();
                                LocalDateTime exStopTime = goblinNftExSkuParam.getExStopTime();

                                // 时间差  以秒表示
                                long millisNum = Duration.between(LocalDateTime.now(), exStopTime).toMillis();

                                // redis 存储
                                goblinRedisUtils.addCode(code, goblinNftExCodeVo, millisNum);
                            }
                            goblinNftExSkuParamMap.put(key, goblinNftExSkuParam);
                            goblinNftExSkus.add(goblinNftExSku);
                        }

                    }

                    break;
                default:

                    // 根据sku减库存
                    int stock = goblinRedisUtils.decrSkuStock(null, goblinNftExSkuParam.getSkuId(), goblinNftExSkuParam.getExStock());
                    if (stock < 0) {
                        goblinRedisUtils.incrSkuStock(null, goblinNftExSkuParam.getSkuId(), goblinNftExSkuParam.getExStock());
                    }else {
                        // 构建兑换码数量
                        for (int i = 0; i < goblinNftExSkuParam.getExStock(); i++) {
                            GoblinNftExCode goblinNftExCode = GoblinNftExCode.getNew();
                            goblinNftExCode.setCodeId(IDGenerator.nextSnowId());
                            goblinNftExCode.setActivityId(goblinNftExSkuParam.getActivityId());

                            // 获取兑换码ZA
                            // 样例 2978-6496-9269-0694-XX
                            String code = IDGenerator.createCode(3, 4, true);
                            goblinNftExCode.setCode(code);
                            goblinNftExCode.setSkuId(goblinNftExSkuParam.getSkuId());
                            goblinNftExCode.setState(1);
                            goblinNftExCode.setCreatedAt(now);
                            goblinNftExCodes.add(goblinNftExCode);

                            GoblinNftExCodeVo goblinNftExCodeVo = GoblinNftExCodeVo.getNew().copy(goblinNftExCode);

                            // 赋值额外属性
                            goblinNftExCodeVo.setStoreId(goblinNftExSkuParam.getStoreId());
                            goblinNftExCodeVo.setExLimit(goblinNftExSkuParam.getExLimit());
                            goblinNftExCodeVo.setExStartTime(goblinNftExSkuParam.getExStartTime());
                            goblinNftExCodeVo.setExStopTime(goblinNftExSkuParam.getExStopTime());
                            goblinNftExCodeVo.setSpuId(goblinNftExSkuParam.getSpuId());
                            // LocalDateTime exStartTime = goblinNftExSkuParam.getExStartTime();
                            LocalDateTime exStopTime = goblinNftExSkuParam.getExStopTime();

                            // 时间差  以秒表示
                            long millisNum = Duration.between(LocalDateTime.now(), exStopTime).toMillis();

                            // redis 存储
                            goblinRedisUtils.addCode(code, goblinNftExCodeVo, millisNum);
                            // goblinNftExCodeArrayList.add(GoblinNftExCodeVo.getNew().copy(goblinNftExCode));
                        }

                        GoblinNftExSkuParam value = goblinNftExSkuParamMap.get(goblinNftExSkuParam.getSkuId());
                        if (value == null) {
                            goblinNftExSkuParamMap.put(goblinNftExSkuParam.getSkuId(), goblinNftExSkuParam);
                        }
                        goblinNftExSkus.add(goblinNftExSku);
                    }


                    // goblinNftExSkuArrayList.add(GoblinNftExSkuVo.getNew().copy(goblinNftExSku));
            }

        }


        for (String key : goblinNftExSkuParamMap.keySet()) {
            GoblinNftExSkuVo goblinNftExSkuVo = goblinRedisUtils.getSkuTime(key);

            GoblinNftExSkuParam goblinNftExSkuParam = goblinNftExSkuParamMap.get(key);

            LocalDateTime exStartTime = goblinNftExSkuParam.getExStartTime(); // "2022-06-26 19:00:00";
            LocalDateTime exStopTime = goblinNftExSkuParam.getExStopTime(); // "2024-06-26 19:00:00";

            if (!StringUtil.isEmpty(goblinNftExSkuVo)) {
                // redis存储 单个sku的开始和结束时间
                LocalDateTime rdExStartTime = LocalDateTime.parse(goblinNftExSkuVo.getRdStartTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); // "2019-06-26 19:00:00";
                LocalDateTime rdExStopTime = LocalDateTime.parse(goblinNftExSkuVo.getRdStopTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); // "2019-06-26 19:00:00";


                // 时间比对
                if (!rdExStartTime.isAfter(exStartTime)) {
                    exStartTime = rdExStartTime;
                }

                if (rdExStopTime.isAfter(exStopTime)) {
                    exStopTime = rdExStopTime;
                }
            }

            GoblinNftExSkuVo goblinNftExSku = GoblinNftExSkuVo.getNew();
            goblinNftExSku.setRdStartTime(exStartTime.toString());
            goblinNftExSku.setRdStopTime(exStopTime.toString());

            goblinRedisUtils.addSkuTime(key,goblinNftExSku);
        }

        log.debug("RDM耗时：ms", System.currentTimeMillis() - startr);

        // 数据库操作
        long startm = System.currentTimeMillis();
        goblinNftExSkuMapper.addGoblinNftExSkus(goblinNftExSkus);
        goblinNftExCodeMapper.addGoblinNftExCodes(goblinNftExCodes);
        log.debug("MSQ耗时：ms", System.currentTimeMillis() - startm);

        return true;
    }

    public static void main(String[] args) {
        String time1 = "2019-06-26 19:00:00";
        String time2 = "2022-06-26 19:00:00";

        String time3 = "2023-06-26 19:00:00";
        String time4 = "2024-06-26 19:00:00";

        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime localDateTime = LocalDateTime.parse(time1, dtf2);
        LocalDateTime localDateTime2 = LocalDateTime.parse(time2, dtf2);

        LocalDateTime localDateTime3 = LocalDateTime.parse(time3, dtf2);
        LocalDateTime localDateTime4 = LocalDateTime.parse(time4, dtf2);

        System.out.println(localDateTime.isAfter(localDateTime2));   // 当time1小于当前时间是返回false
        System.out.println(localDateTime3.isAfter(localDateTime4));

    }


    /**
     * 获取每个sku的兑换码生成数量
     *
     * @param exStock
     * @param map
     * @return
     */
    private Map<String, Integer> getSkuHitRatio(Integer exStock, Map<String, BigDecimal> map) {

        // sku ---> 次数
        Map<String, Integer> skuNumMap = new HashMap<>();

        for (String key : map.keySet()) {

            if (map.get(key) == null) {
                System.out.println(map.get(key));
            }
            // 概率
            BigDecimal hitNum = map.get(key).divide(BigDecimal.valueOf(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
            Integer stock = hitNum.multiply(BigDecimal.valueOf(exStock)).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
            skuNumMap.put(key, stock);
        }
        return skuNumMap;
    }


    // 各种状态下判断藏品是否可以展示
    public boolean getSkuAllStatusShow(GoblinGoodsSku info) {
        if (
                info != null
                        && info.getSkuType() == 1
                        && info.getStatus().equals("3")
                        && info.getShelvesStatus().equals("3")
                        && (info.getSkuAppear() == null || info.getSkuAppear().equals("0"))
                        && info.getDelFlg().equals("0")
                        && info.getUnbox().equals("0")) {
            return true;
        } else {
            return false;
        }
    }


}
