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.DateUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.manage.GoblinStorePurchaseCommonParam;
import com.liquidnet.service.goblin.dto.manage.GoblinStorePurchaseItemParam;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.entity.GoblinStoreMarketPurchasing;
import com.liquidnet.service.goblin.entity.GoblinStoreMarketing;
import com.liquidnet.service.goblin.service.manage.IGoblinStorePurchasingService;
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.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

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

@Service
public class GoblinStorePurchasingServiceImpl implements IGoblinStorePurchasingService {

    @Autowired
    GoblinRedisUtils goblinRedisUtils;
    @Autowired
    GoblinMongoUtils goblinMongoUtils;
    @Autowired
    QueueUtils queueUtils;

    @Override
    public ResponseDto<PageInfo<GoblinStoreMarketVo>> purchasingList(int page, String purchaseName, int status, String st, String et, String ct) {
        PageInfo pageInfo = new PageInfo();
        LocalDateTime now = LocalDateTime.now();
        HashMap<String, Object> map = goblinMongoUtils.getStoreMarketList(page, purchaseName, status, st, et, ct);
        List<GoblinStoreMarketVo> list = (List<GoblinStoreMarketVo>) map.get("data");
        for (GoblinStoreMarketVo item : list) {
            if (item.getStatus().equals(7)) {
                item.setStatus(7);
            } else if (LocalDateTime.parse(item.getStartTime(), DTF_YMD_HMS).isAfter(now)) {
                item.setStatus(0);
            } else if (LocalDateTime.parse(item.getEndTime(), DTF_YMD_HMS).isBefore(now)) {
                item.setStatus(2);
            } else {
                item.setStatus(1);
            }
        }
        pageInfo.setList(list);
        pageInfo.setTotal((Long) map.get("total"));
        return ResponseDto.success(pageInfo);
    }

    @Override
    public ResponseDto<Boolean> purchasingStatus(String marketId, String storeId, int status) {
        GoblinStoreMarketing bean = GoblinStoreMarketing.getNew();
        LocalDateTime now = LocalDateTime.now();
        bean.setUpdatedAt(now);
        switch (status) {
            case 0:
            case 7:
                bean.setStatus(status);
                bean.setDelFlag(0);
                GoblinStoreMarketVo vo = GoblinStoreMarketVo.getNew();
                vo.setStatus(status);
                goblinMongoUtils.updateStoreMarket(marketId, storeId, vo);
                vo = goblinRedisUtils.getGoblinStoreMarketVo(marketId);
                vo.setStatus(status);
                goblinRedisUtils.setGoblinStoreMarketVo(marketId, vo);
                break;
            case -1:
                bean.setStatus(7);
                bean.setDelFlag(1);
                goblinMongoUtils.delStoreMarket(marketId, storeId);
                goblinRedisUtils.delGoblinStoreMarketVo(marketId);
                break;
        }
        //mysql
        queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_STORE_MARKET.getKey(),
                SqlMapping.get("goblin.store.market.status", bean.getStatus(), bean.getDelFlag(), marketId, storeId));
        return ResponseDto.success();
    }

    @Override
    public ResponseDto<Boolean> purchasingInsert(String purchaseName, String storeId, String st, String et, Integer isPre, String preTime) {
        String storeMarketId = IDGenerator.nextTimeId2();
        GoblinStoreMarketing bean = GoblinStoreMarketing.getNew();
        bean.setStoreMarketId(storeMarketId);
        bean.setName(purchaseName);
        bean.setType(2);
        bean.setStatus(0);
        bean.setStoreId(storeId);
        bean.setDescribes("");
        bean.setStartTime(LocalDateTime.parse(st, DTF_YMD_HMS));
        bean.setEndTime(LocalDateTime.parse(et, DTF_YMD_HMS));
        bean.setDelFlag(0);
        bean.setIsPre(isPre);
        if (isPre == 1) {
            bean.setPreTime(LocalDateTime.parse(preTime, DTF_YMD_HMS));
        } else {
            bean.setPreTime(null);
        }
        bean.setCreatedAt(LocalDateTime.now());

        GoblinStoreMarketVo vo = GoblinStoreMarketVo.getNew();
        BeanUtils.copyProperties(bean, vo);
        vo.setStartTime(st);
        vo.setEndTime(et);
        vo.setCreatedAt(DateUtil.getNowTime());
        vo.setPreTime(preTime);
        //mongo
        goblinMongoUtils.insertStoreMarket(vo);
        //redis
        goblinRedisUtils.setGoblinStoreMarketVo(storeMarketId, vo);
        //mysql
        queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_STORE_MARKET.getKey(),
                SqlMapping.get("goblin.store.market.insert", bean.getStoreMarketId(), bean.getName(), bean.getType(), bean.getStatus(), bean.getStoreId(), bean.getStartTime(), bean.getEndTime(), bean.getDelFlag(), bean.getIsPre(), bean.getPreTime(), bean.getCreatedAt()));
        return ResponseDto.success();
    }

    @Override
    public ResponseDto<Boolean> purchasingUpdate(String marketId, String purchaseName, String storeId, String st, String et, Integer isPre, String preTime) {
        GoblinStoreMarketing bean = GoblinStoreMarketing.getNew();
        bean.setName(purchaseName);
        bean.setType(2);
        bean.setStatus(0);
        bean.setStoreId(storeId);
        bean.setDescribes("");
        bean.setStartTime(LocalDateTime.parse(st, DTF_YMD_HMS));
        bean.setEndTime(LocalDateTime.parse(et, DTF_YMD_HMS));
        bean.setDelFlag(0);
        bean.setIsPre(isPre);
        if (isPre == 1) {
            bean.setPreTime(LocalDateTime.parse(preTime, DTF_YMD_HMS));
        } else {
            bean.setPreTime(null);
        }
        bean.setUpdatedAt(LocalDateTime.now());

        GoblinStoreMarketVo vo = GoblinStoreMarketVo.getNew();
        BeanUtils.copyProperties(bean, vo);
        //mongo
        goblinMongoUtils.updateStoreMarket(marketId, storeId, vo);
        //redis
        goblinRedisUtils.setGoblinStoreMarketVo(marketId, vo);
        //mysql
        queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_STORE_MARKET.getKey(),
                SqlMapping.get("goblin.store.market.update", bean.getName(), bean.getType(), bean.getStatus(), bean.getStoreId(), bean.getDescribes(), bean.getStartTime(), bean.getEndTime(), bean.getDelFlag(), bean.getIsPre(), bean.getPreTime(), bean.getUpdatedAt(), marketId, bean.getStoreId()));
        return ResponseDto.success();
    }

    @Override
    public ResponseDto<GoblinStoreMarketVo> purchasingDetails(String marketId) {
        return ResponseDto.success(goblinRedisUtils.getGoblinStoreMarketVo(marketId));
    }

    @Override
    public ResponseDto<List<GoblinMarketSpuListVo>> purchasingSpuList(String marketId, String storeId, int page) {
        int size = 20;
        List<GoblinStoreMarketIsConfigVo> spuIds = goblinRedisUtils.getStoreMarketIsConfig(marketId, storeId);
        List<String> marketSpuList = spuIds.stream().map(GoblinStoreMarketIsConfigVo::getMarketSpuId).collect(Collectors.toList());
        List<GoblinMarketSpuListVo> voList = ObjectUtil.getGoblinMarketSpuListVoArrayList();
        int count = page * size;
        int startCount = (page - 1) * size;
        if (count >= marketSpuList.size()) {
            count = marketSpuList.size();
        }
        for (int i = startCount; i < count; i++) {
            GoblinMarketSpuListVo vo = GoblinMarketSpuListVo.getNew();
            String marketSpuId = marketSpuList.get(i);
            GoblinGoodsInfoVo spuVo = goblinRedisUtils.getGoodsInfoVo(marketSpuId);
            vo.setMarketSpuId(marketSpuId.split(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue())[0]);
            vo.setCoverPic(spuVo.getCoverPic());
            vo.setName(spuVo.getName());
            vo.setPriceGe(spuVo.getPriceGe());
            vo.setPriceLe(spuVo.getPriceLe());
            voList.add(vo);
        }
        return ResponseDto.success(voList);
    }

    @Override
    public ResponseDto<List<GoblinStorePurchaseSkuVo>> purchasingSkuList(String marketId, String storeId, String marketSpuId) {
        GoblinGoodsInfoVo marketSpuVo = goblinRedisUtils.getGoodsInfoVo(marketSpuId);
        List<String> marketSkuIdList = marketSpuVo.getSkuIdList();
        List<GoblinStorePurchaseSkuVo> voList = ObjectUtil.getGoblinStorePurchaseSkuVoArrayList();
        for (String marketSkuId : marketSkuIdList) {
            GoblinGoodsSkuInfoVo marketSkuVo = goblinRedisUtils.getGoodsSkuInfoVo(marketSkuId);
            GoblinGoodsSkuInfoVo skuVo = goblinRedisUtils.getGoodsSkuInfoVo(marketSkuId.split(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue())[0]);
            GoblinStorePurchaseSkuVo vo = GoblinStorePurchaseSkuVo.getNew();
            vo.setMarketSkuId(marketSkuId);
            vo.setSkuSpecList(marketSkuVo.getSkuSpecList());
            vo.setPrice(skuVo.getPrice());
            vo.setStock(skuVo.getStock());
            vo.setSkuStock(skuVo.getSkuStock());
            vo.setPriceMarketing(marketSkuVo.getPrice());
            vo.setStockMarketing(marketSkuVo.getSkuStock());
            vo.setBuyFactor(marketSkuVo.getBuyFactor());
            vo.setBuyLimit(marketSkuVo.getBuyLimit());
            vo.setBuyRoster(marketSkuVo.getBuyRoster());
            voList.add(vo);
        }
        return ResponseDto.success(voList);
    }

    @Override
    public ResponseDto<Boolean> purchasingSkuInsert(GoblinStorePurchaseCommonParam params) {
        LocalDateTime now = LocalDateTime.now();
        String marketSpuId = params.getSpuId().concat(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue()).concat(IDGenerator.marketGoodId(params.getStoreMarketId()));
        GoblinMarketRelationVo relationVo = GoblinMarketRelationVo.getNew();
        relationVo.setSpuId(params.getSpuId());
        relationVo.setStoreId(params.getStoreId());
        List<String> skuList = CollectionUtil.arrayListString();//skuId数组
        List<String> marketSkuList = CollectionUtil.arrayListString();//活动skuId数组
        List<String> errorNameList = CollectionUtil.arrayListString();//修改失败的款式名称数组
        List<BigDecimal> priceList = CollectionUtil.arrayListBigDecimal();//价格集合
        LinkedList<String> sqls = CollectionUtil.linkedListString();
        sqls.add(SqlMapping.get("goblin.store.market.insertRelation"));
        LinkedList<Object[]> sqlsData = CollectionUtil.linkedListObjectArr();
        for (GoblinStorePurchaseItemParam item : params.getGoblinStorePurchaseItemParam()) {
            String purchaseId = IDGenerator.nextMilliId2();
            GoblinStoreMarketPurchasing bean = GoblinStoreMarketPurchasing.getNew();
            bean.setStoreId(params.getStoreId());
            bean.setStoreMarketId(params.getStoreMarketId());
            bean.setSpuId(params.getSpuId());
            bean.setPurchaseId(purchaseId);
            bean.setSkuId(item.getSkuId());
            bean.setPriceMarketing(item.getPriceMarketing());
            bean.setStockMarketing(item.getStockMarketing());
            bean.setBuyLimit(item.getBuyLimit());
            bean.setBuyFactor(item.getBuyFactor());
            bean.setBuyRoster(item.getBuyRoster());
            bean.setDelFlag(0);
            bean.setCreatedAt(now);
            //mongo
            GoblinGoodsSkuInfoVo skuVo = goblinRedisUtils.getGoodsSkuInfoVo(item.getSkuId());
            //判断库存相关
            int restStock = goblinRedisUtils.decrSkuStock(null, item.getSkuId(), item.getStockMarketing());
            if (restStock < 0) {
                errorNameList.add(skuVo.getName());
                goblinRedisUtils.incrSkuStock(null, item.getSkuId(), item.getStockMarketing());
                continue;
            }
            goblinRedisUtils.setSkuStock(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue(), item.getSkuId(), item.getStockMarketing());
            skuVo.setSpuId(marketSpuId);
            skuVo.setSkuId(item.getSkuId().concat(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue()).concat(IDGenerator.marketGoodId(params.getStoreMarketId())));
            skuVo.setPrice(bean.getPriceMarketing());
            skuVo.setPriceMember(bean.getPriceMarketing());
            skuVo.setSkuStock(bean.getStockMarketing());
            skuVo.setBuyLimit(bean.getBuyLimit());
            skuVo.setBuyRoster(bean.getBuyRoster());
            skuVo.setBuyFactor(bean.getBuyFactor().toString());
            skuVo.setMarketId(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue().concat(params.getStoreMarketId()));
            goblinMongoUtils.setGoodsSkuInfoVo(skuVo);
            //redis
            goblinRedisUtils.setGoodsSkuInfoVo(skuVo);
            //mysql
            sqlsData.add(new Object[]{purchaseId, bean.getStoreMarketId(), bean.getSpuId(), bean.getSpuId(), bean.getStoreId(), bean.getPriceMarketing(),
                    bean.getStockMarketing(), bean.getBuyFactor(), bean.getBuyRoster(), bean.getBuyLimit(), bean.getDelFlag(), bean.getCreatedAt()});
            marketSkuList.add(skuVo.getSkuId());
            skuList.add(item.getSkuId());
            priceList.add(item.getPriceMarketing());
        }
        if (errorNameList.size() == params.getGoblinStorePurchaseItemParam().size()) {
            return ResponseDto.failure(JsonUtils.toJson(errorNameList));
        }
        //mongo
        GoblinGoodsInfoVo spuVo = goblinRedisUtils.getGoodsInfoVo(params.getSpuId());
        spuVo.setSpuId(marketSpuId);
        spuVo.setSkuIdList(marketSkuList);
        //排序
        priceList = priceList.stream().sorted().collect(Collectors.toList());
        spuVo.setPriceGe(priceList.get(0));
        spuVo.setPriceLe(priceList.get(priceList.size() - 1));
        spuVo.setMarketId(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue().concat(params.getStoreMarketId()));
        goblinMongoUtils.setGoodsInfoVo(spuVo);
        //redis
        goblinRedisUtils.setGoodsInfoVo(spuVo);
        relationVo.setSkuList(skuList);
        goblinRedisUtils.addMarketRelation(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue(), params.getStoreMarketId(), relationVo);
        goblinRedisUtils.addStoreMarketIsConfig(params.getStoreMarketId(), params.getStoreId(), params.getSpuId(), marketSpuId);
        // 执行sql
        String sqlData = SqlMapping.gets(sqls, sqlsData);
        queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_STORE_MARKET.getKey(),
                sqlData);
        if (errorNameList.size() > 0) {
            return ResponseDto.failure(JsonUtils.toJson(errorNameList));
        }
        return ResponseDto.success();
    }

    @Override
    public ResponseDto<Boolean> purchasingSkuUpdate(GoblinStorePurchaseCommonParam params) {
        LocalDateTime now = LocalDateTime.now();
        String marketSpuId = params.getSpuId().concat(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue()).concat(IDGenerator.marketGoodId(params.getStoreMarketId()));
        List<String> marketSkuList = CollectionUtil.arrayListString();
        List<BigDecimal> priceList = CollectionUtil.arrayListBigDecimal();//价格集合
        List<String> errorNameList = CollectionUtil.arrayListString();//修改失败的款式名称数组
        LinkedList<String> sqls = CollectionUtil.linkedListString();
        sqls.add(SqlMapping.get("goblin.store.market.updateRelation"));
        LinkedList<Object[]> sqlsData = CollectionUtil.linkedListObjectArr();
        for (GoblinStorePurchaseItemParam item : params.getGoblinStorePurchaseItemParam()) {
            GoblinStoreMarketPurchasing bean = GoblinStoreMarketPurchasing.getNew();
            bean.setPriceMarketing(item.getPriceMarketing());
            bean.setStockMarketing(item.getStockMarketing());
            bean.setBuyLimit(item.getBuyLimit());
            bean.setBuyFactor(item.getBuyFactor());
            bean.setBuyRoster(item.getBuyRoster());
            bean.setDelFlag(0);
            bean.setUpdatedAt(now);
            //mongo
            GoblinGoodsSkuInfoVo skuVo = goblinRedisUtils.getGoodsSkuInfoVo(item.getSkuId().concat(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue()).concat(IDGenerator.marketGoodId(params.getStoreMarketId())));
            int changeStock = item.getStockMarketing() - skuVo.getSkuStock();
            //判断库存相关
            int restStock;
            if (changeStock > 0) {
                restStock = goblinRedisUtils.incrSkuStock(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue(), item.getSkuId(), changeStock);
                goblinRedisUtils.decrSkuStock(null, item.getSkuId(), changeStock);
            } else {
                restStock = goblinRedisUtils.decrSkuStock(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue(), item.getSkuId(), -changeStock);
                goblinRedisUtils.incrSkuStock(null, item.getSkuId(), -changeStock);
            }
            if (restStock < 0) {
                errorNameList.add(skuVo.getName());
                goblinRedisUtils.incrSkuStock(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue(), item.getSkuId(), -changeStock);
                goblinRedisUtils.decrSkuStock(null, item.getSkuId(), -changeStock);
                continue;
            }
            skuVo.setPrice(bean.getPriceMarketing());
            skuVo.setPriceMember(bean.getPriceMarketing());
            skuVo.setSkuStock(bean.getStockMarketing());
            skuVo.setBuyLimit(bean.getBuyLimit());
            skuVo.setBuyRoster(bean.getBuyRoster());
            skuVo.setBuyFactor(bean.getBuyFactor().toString());
            skuVo.setMarketId(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue().concat(params.getStoreMarketId()));
            goblinMongoUtils.updateGoodsSkuInfoVo(skuVo);
            //redis
            goblinRedisUtils.setGoodsSkuInfoVo(skuVo);
            //mysql
            sqlsData.add(new Object[]{bean.getPriceMarketing(),
                    bean.getStockMarketing(), bean.getBuyFactor(), bean.getBuyRoster(), bean.getBuyLimit(), bean.getUpdatedAt(), params.getStoreMarketId(), params.getStoreId()});
            marketSkuList.add(skuVo.getSkuId());
            priceList.add(bean.getPriceMarketing());
        }
        if (errorNameList.size() == params.getGoblinStorePurchaseItemParam().size()) {
            return ResponseDto.failure(JsonUtils.toJson(errorNameList));
        }
        //mongo
        GoblinGoodsInfoVo spuVo = goblinRedisUtils.getGoodsInfoVo(params.getSpuId());
        spuVo.setSpuId(marketSpuId);
        //排序
        priceList = priceList.stream().sorted().collect(Collectors.toList());
        spuVo.setPriceGe(priceList.get(0));
        spuVo.setPriceLe(priceList.get(priceList.size() - 1));
        spuVo.setSkuIdList(marketSkuList);
        spuVo.setMarketId(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue().concat(params.getStoreMarketId()));
        goblinMongoUtils.updateGoodsInfoVo(spuVo);
        //redis
        goblinRedisUtils.setGoodsInfoVo(spuVo);
        // 执行sql
        String sqlData = SqlMapping.gets(sqls, sqlsData);
        queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_STORE_MARKET.getKey(),
                sqlData);
        if (errorNameList.size() > 0) {
            return ResponseDto.failure(JsonUtils.toJson(errorNameList));
        }
        return ResponseDto.success();
    }

    @Override
    public ResponseDto<Boolean> purchasingSpuDel(String marketId, String storeId, String spuId) {
        //todo 判断 如果有订单待支付 则不能关闭
        LocalDateTime now = LocalDateTime.now();
        String marketSpuId = spuId.concat(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue()).concat(IDGenerator.marketGoodId(marketId));
        GoblinStoreMarketPurchasing bean = GoblinStoreMarketPurchasing.getNew();
        bean.setUpdatedAt(now);
        bean.setDelFlag(1);
        //mongo
        goblinMongoUtils.delGoodsInfoVo(marketSpuId);
        //redis
        goblinRedisUtils.delGoodsInfoVo(marketSpuId);
        goblinRedisUtils.removeMarketRelation(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue(), marketId, spuId);
        goblinRedisUtils.delStoreMarketIsConfig(marketId, storeId, spuId, marketSpuId);
        //库存处理
        GoblinGoodsInfoVo marketVo = goblinRedisUtils.getGoodsInfoVo(marketSpuId);
        for (String marketSkuId : marketVo.getSkuIdList()) {
            String skuId = marketSkuId.split(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue())[0];
            //库存回滚
            int restStock = goblinRedisUtils.getSkuStock(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue(), marketSkuId);
            int restStockDe = goblinRedisUtils.decrSkuStock(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue(), marketSkuId, restStock);
            goblinRedisUtils.incrSkuStock(null, skuId, restStock + restStockDe);
        }
        //mysql
        queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_STORE_MARKET.getKey(),
                SqlMapping.get("goblin.store.market.delSpuRelation", bean.getDelFlag(), bean.getUpdatedAt(), marketId, storeId, spuId));
        return ResponseDto.success();
    }
}
