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

import com.github.pagehelper.PageInfo;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.base.PagedResult;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.param.GoblinListCreateItemParam;
import com.liquidnet.service.goblin.param.GoblinListCreateParam;
import com.liquidnet.service.goblin.param.GoblinListUpdateParam;
import com.liquidnet.service.goblin.service.manage.IGoblinListService;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import static com.liquidnet.commons.lang.util.DateUtil.DTF_YMD_HMS;

/**
 * <p>
 * 商城-名单表 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2022-04-29
 */
@Service
public class GoblinListServiceImpl implements IGoblinListService {

    @Autowired
    GoblinRedisUtils redisUtils;
    @Autowired
    GoblinMongoUtils mongoUtils;
    @Autowired
    QueueUtils queueUtils;

    @Override
    public ResponseDto<PageInfo<GoblinListVo>> getList(String name, Integer page) {
        PageInfo<GoblinListVo> pageResult;
        HashMap<String, Object> map = mongoUtils.getGoblinListVo(name, CurrentUtil.getCurrentUid(), page);
        List<GoblinListDetailsVo> detailsVoList = (List<GoblinListDetailsVo>) map.get("data");
        List<GoblinListVo> voList = ObjectUtil.getGoblinListVo();
        for (GoblinListDetailsVo item : detailsVoList) {
            GoblinListVo vo = GoblinListVo.getNew();
            vo.setListId(item.getListId());
            vo.setName(item.getName());
            vo.setTimeStart(item.getTimeStart());
            vo.setTimeEnd(item.getTimeEnd());
            vo.setSkuCount(item.getItemVo().size());
            vo.setHasBlack(item.getBlackUrl().equals("") ? 0 : 1);
            voList.add(vo);
        }
        pageResult = new PageInfo(voList);
        pageResult.setTotal((Long) map.get("total"));
        return ResponseDto.success(pageResult);
    }

    @Override
    public ResponseDto<GoblinListDetailsVo> getDetails(String listId) {
        GoblinListDetailsVo vo = redisUtils.getGoblinListDetailsVo(listId);
        if (vo == null || !vo.getUid().equals(CurrentUtil.getCurrentUid())) {
            return ResponseDto.failure("信息错误");
        }
        for (GoblinListDetailsItemVo item : vo.getItemVo()) {
            GoblinGoodsSkuInfoVo skuVo = redisUtils.getGoodsSkuInfoVo(item.getSkuId());
            item.setSkuName(skuVo.getName());
            item.setSurplusStock(redisUtils.getSkuStock(listId, skuVo.getSkuId()));
//            if (skuVo.getUnbox().equals("0")) {
//                item.setSurplusStock(redisUtils.getSkuStock(null, item.getSkuId()));
//                item.setStock(skuVo.getSkuStock());
//            } else {
//                List<String> skuIdList = redisUtils.getGoodsInfoVo(item.getSpuId()).getSkuIdList();
//                int surplusStock = 0;
//                int stock = 0;
//                for (String skuIdItem : skuIdList) {// 盲盒计算所有sku库存总数
//                    if (skuIdItem.equals(item.getSkuId())) {// 过滤自己
//                        stock += skuVo.getSkuStock();
//                        continue;
//                    }
//                    GoblinGoodsSkuInfoVo itemVo = redisUtils.getGoodsSkuInfoVo(skuIdItem);
//                    surplusStock += redisUtils.getSkuAllStatusStock(itemVo);
//                    stock += itemVo.getSkuStock();
//                }
//                item.setSurplusStock(surplusStock);
//                item.setStock(stock);
//            }
        }
        return ResponseDto.success(vo);
    }

    @Override
    public ResponseDto<Boolean> create(GoblinListCreateParam param) {
        LinkedList<String> sqls = CollectionUtil.linkedListString();
        sqls.add(SqlMapping.get("goblin_list_insert"));
        sqls.add(SqlMapping.get("goblin_list_detail_insert"));
        LinkedList<Object[]> goblinList = CollectionUtil.linkedListObjectArr();
        LinkedList<Object[]> goblinListDetails = CollectionUtil.linkedListObjectArr();
        LocalDateTime now = LocalDateTime.now();

        //时间
        if (param.getItemParams().size() > 1) {
            return ResponseDto.failure("只能配置一个sku");
        }
        String skuId = param.getItemParams().get(0).getSkuId();
        GoblinGoodsSkuInfoVo skuInfoVo = redisUtils.getGoodsSkuInfoVo(skuId);
        LocalDateTime st = LocalDateTime.parse(param.getTimeStart(), DTF_YMD_HMS);
        LocalDateTime et = null;
        List<GoblinListCollectVo> collectVos;
        if (param.getTimeEnd() != null) {//传结束时间
            et = LocalDateTime.parse(param.getTimeEnd(), DTF_YMD_HMS);
            if (st.isAfter(et)) {
                return ResponseDto.failure("开始时间不能晚于结束时间");
            }
            if (et.isAfter(skuInfoVo.getSaleStartTime())) {
                return ResponseDto.failure("结束时间不能晚于商品开售时间");
            }
            collectVos = redisUtils.getGoblinListCollect(skuId);
            for (GoblinListCollectVo collectItem : collectVos) {
                if (collectItem.getTimeEnd() != null) {
                    if ((st.isAfter(collectItem.getTimeStart().minusSeconds(1)) && st.isBefore(collectItem.getTimeEnd().minusSeconds(1))) ||
                            (et.isAfter(collectItem.getTimeStart().minusSeconds(1)) && et.isBefore(collectItem.getTimeEnd().minusSeconds(1))) ||
                            (st.isBefore(collectItem.getTimeStart().minusSeconds(1)) && et.isAfter(collectItem.getTimeEnd().minusSeconds(1)))
                    ) {//开始时间不能在其他时间段内/结束间不能在其他时间段内/开始结束时间不能包含其他时间段
                        return ResponseDto.failure("sku时间不能重合");
                    }
                } else {
                    if (st.isBefore(collectItem.getTimeStart().minusSeconds(1)) && et.isAfter(collectItem.getTimeStart().minusSeconds(1))) {
                        return ResponseDto.failure("sku时间不能重合");//开始结束时间不能包含只有开始时间的时间段
                    }
                }
            }
        } else {//未结束时间
            if (st.isAfter(skuInfoVo.getSaleStartTime())) {
                return ResponseDto.failure("结束时间不能晚于商品开售时间");
            }
            collectVos = redisUtils.getGoblinListCollect(skuId);
            for (GoblinListCollectVo collectItem : collectVos) {
                if (collectItem.getTimeEnd() != null) {
                    if (st.isAfter(collectItem.getTimeStart().minusSeconds(1)) && st.isBefore(collectItem.getTimeEnd().minusSeconds(1))) {
                        return ResponseDto.failure("sku时间不能重合");
                    }
                } else {

                }
            }
        }

        GoblinListDetailsVo vo = GoblinListDetailsVo.getNew();
        List<GoblinListDetailsItemVo> voItemList = ObjectUtil.goblinListDetailsItemVoArrayList();
        vo.setListId(IDGenerator.nextTimeId2());
        vo.setUid(CurrentUtil.getCurrentUid());
        vo.setName(param.getName());
        vo.setTagType(param.getTagType());
        vo.setTimeStart(param.getTimeStart());
        vo.setTimeEnd(param.getTimeEnd());
        vo.setWhiteType(param.getWhiteType());
        vo.setCreatedAt(DateUtil.format(now, DateUtil.Formatter.yyyyMMddHHmmss));
        //判断 白名单类型
        if (param.getWhiteType().equals(1)) {//需要xls文件
            if (param.getWhiteUrl() == null || param.getWhiteUrl().equals("")) {
                return ResponseDto.failure("未上传指定用户文件");
            }
            vo.setWhiteUrl(param.getWhiteUrl());
            vo.setWhiteName(param.getWhiteName());
        } else {//不需要xls文件
            vo.setWhiteUrl("");
            vo.setWhiteName("");
        }
        vo.setBlackName(param.getBlackName() == null ? "" : param.getBlackName());
        vo.setBlackUrl(param.getBlackUrl() == null ? "" : param.getBlackUrl());
        for (GoblinListCreateItemParam item : param.getItemParams()) {
            GoblinListDetailsItemVo itemVo = GoblinListDetailsItemVo.getNew();
            itemVo.setSkuId(item.getSkuId());
            itemVo.setSpuId(item.getSpuId());
            itemVo.setPrice(item.getPrice());
            itemVo.setPriceV(item.getPriceV());
            itemVo.setSkuStock(item.getSkuStock());
            itemVo.setProductId(item.getProductId());
            voItemList.add(itemVo);
            //库存
            int skuStock = redisUtils.decrSkuStock(null, itemVo.getSkuId(), itemVo.getSkuStock());
            if (skuStock < 0) {
                redisUtils.incrSkuStock(null, itemVo.getSkuId(), itemVo.getSkuStock());
                return ResponseDto.failure("库存不足");
            } else {
                redisUtils.setSkuStock(vo.getListId(), itemVo.getSkuId(), itemVo.getSkuStock());
            }
            //集合
            GoblinListCollectVo collectVo = GoblinListCollectVo.getNew();
            collectVo.setSpuId(itemVo.getSpuId());
            collectVo.setSkuId(itemVo.getSkuId());
            collectVo.setPrice(itemVo.getPrice());
            collectVo.setPriceV(itemVo.getPriceV());
            collectVo.setProductId(itemVo.getProductId());
            collectVo.setWhiteType(vo.getWhiteType());
            collectVo.setTimeStart(st);
            collectVo.setTimeEnd(et);
            collectVo.setTagType(vo.getTagType());
            collectVo.setListId(vo.getListId());
            collectVos.add(collectVo);
            redisUtils.setGoblinListCollect(itemVo.getSkuId(), collectVos);
            // 白名单
            queueUtils.sendMsgByRedisXls(vo.getListId(), vo.getWhiteUrl(), "", "3", item.getSkuId());
            // 黑名单
            queueUtils.sendMsgByRedisXls(vo.getListId(), vo.getBlackUrl(), "", "4", item.getSkuId());
            goblinListDetails.add(new Object[]{
                    vo.getListId(), itemVo.getSpuId(), itemVo.getSkuId(), now, itemVo.getSkuStock(), itemVo.getPriceV(), itemVo.getProductId(), itemVo.getPrice()
            });
        }
        vo.setItemVo(voItemList);
        redisUtils.setGoblinListDetailsVo(vo);
        mongoUtils.insertGoblinListDetailsVo(vo);
        goblinList.add(new Object[]{
                vo.getListId(), vo.getUid(), vo.getName(), vo.getWhiteType(), vo.getWhiteUrl(), vo.getTimeStart(), vo.getTimeEnd(), vo.getTagType(), vo.getBlackUrl(), now
        });
        queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_STORE_MARKET.getKey(), SqlMapping.gets(sqls, goblinList, goblinListDetails));
        return ResponseDto.success();
    }

    @Override
    public ResponseDto<Boolean> update(GoblinListUpdateParam param) {
        String whiteUrl = "";
        String blackUrl = "";
        LocalDateTime now = LocalDateTime.now();
        GoblinListDetailsVo vo = redisUtils.getGoblinListDetailsVo(param.getListId());
        if (vo == null || !vo.getUid().equals(CurrentUtil.getCurrentUid())) {
            return ResponseDto.failure("信息错误");
        }
        whiteUrl = vo.getWhiteUrl();
        blackUrl = vo.getBlackUrl();
        //判断 白名单类型
        vo.setWhiteType(param.getWhiteType());
        if (param.getWhiteType().equals(1)) {//需要xls文件
            if (param.getWhiteUrl() == null || param.getWhiteUrl().equals("")) {
                return ResponseDto.failure("未上传指定用户文件");
            }
            vo.setWhiteUrl(param.getWhiteUrl());
            vo.setWhiteName(param.getWhiteName());
        } else {//不需要xls文件
            vo.setWhiteUrl("");
            vo.setWhiteName("");
        }
        vo.setBlackUrl(param.getBlackUrl() == null ? "" : param.getBlackUrl());
        vo.setBlackName(param.getBlackName() == null ? "" : param.getBlackName());
        for (GoblinListDetailsItemVo item : vo.getItemVo()) {
            // 白名单
            queueUtils.sendMsgByRedisXls(vo.getListId(), param.getWhiteUrl(), whiteUrl, "3", item.getSkuId());
            // 黑名单
            queueUtils.sendMsgByRedisXls(vo.getListId(), param.getBlackUrl(), blackUrl, "4", item.getSkuId());
        }
        List<GoblinListCollectVo> collectVos = redisUtils.getGoblinListCollect(vo.getItemVo().get(0).getSkuId());
        for (GoblinListCollectVo itemVo:collectVos){
            if(itemVo.getListId().equals(param.getListId())){
                itemVo.setWhiteType(vo.getWhiteType());
                break;
            }
        }
        redisUtils.setGoblinListCollect(vo.getItemVo().get(0).getSkuId(),collectVos);
        redisUtils.setGoblinListDetailsVo(vo);
        mongoUtils.changeGoblinListDetailsVo(vo);
        //sql入库
        queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_STORE_MARKET.getKey(),
                SqlMapping.get("goblin_list_update", param.getWhiteUrl(), param.getWhiteType(), param.getBlackUrl(), now, param.getListId()));
        return ResponseDto.success();
    }

    @Override
    public ResponseDto<Boolean> delete(String listId) {
        LocalDateTime now = LocalDateTime.now();
        GoblinListDetailsVo vo = redisUtils.getGoblinListDetailsVo(listId);
        if (vo == null || !vo.getUid().equals(CurrentUtil.getCurrentUid())) {
            return ResponseDto.failure("信息错误");
        }
        for (GoblinListDetailsItemVo item : vo.getItemVo()) {
            // 白名单
            queueUtils.sendMsgByRedisXls(vo.getListId(), "", vo.getWhiteUrl(), "3", item.getSkuId());
            // 黑名单
            queueUtils.sendMsgByRedisXls(vo.getListId(), "", vo.getBlackUrl(), "4", item.getSkuId());
        }

        //库存
        int restStock = redisUtils.getSkuStock(vo.getListId(), vo.getItemVo().get(0).getSkuId());
        if (restStock > 0) {
            redisUtils.incrSkuStock(null, vo.getItemVo().get(0).getSkuId(), restStock);
        }

        redisUtils.delGoblinListCollect(vo.getItemVo().get(0).getSkuId(), listId);
        redisUtils.delGoblinListDetailsVo(listId);
        mongoUtils.removeGoblinListDetailsVo(listId);
        //sql入库
        queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_STORE_MARKET.getKey(),
                SqlMapping.get("goblin_list_remove", now, listId));
        return ResponseDto.success();
    }
}
