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

import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.DateUtil;
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.erp.config.ErpWdtClient;
import com.liquidnet.service.erp.constant.ErpEnum;
import com.liquidnet.service.erp.utils.ErpObjectUtil;
import com.liquidnet.service.erp.vo.StockQueryBaseVo;
import com.liquidnet.service.erp.vo.StockQueryVo;
import com.liquidnet.service.erp.vo.SyncStockVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSkuInfoVo;
import com.liquidnet.service.goblin.mapper.GoblinGoodsSkuMapper;
import com.liquidnet.service.goblin.service.IGoblinErpService;
import com.liquidnet.service.platform.utils.GoblinRedisUtils;
import com.liquidnet.service.platform.utils.QueueUtils;
import com.mongodb.BasicDBObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 支付订单表 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2021-07-20
 */
@Service
@Slf4j
public class WdtServiceImpl implements IGoblinErpService {

    @Autowired
    ErpWdtClient erpWdtClient;
    @Autowired
    GoblinGoodsSkuMapper goblinGoodsSkuMapper;
    @Autowired
    GoblinRedisUtils goblinRedisUtils;
    @Autowired
    MongoTemplate mongoTemplate;
    @Autowired
    MongoConverter mongoConverter;
    @Autowired
    QueueUtils queueUtils;

    @Override
    public ResponseDto<Boolean> initErpStock(String spuId, int min) {
        try {
            Date nowTime = DateUtil.now();
            String json;
            Map<String, String> param = CollectionUtil.linkMapStringString();
            param.put("start_time", DateUtil.format(DateUtil.addMin(nowTime, -min), DateUtil.Formatter.yyyyMMddHHmmss));
            param.put("end_time", DateUtil.format(nowTime, DateUtil.Formatter.yyyyMMddHHmmss));
            if (null != spuId && !"".equals(spuId)) {
                //查询 spu下的sku
                GoblinGoodsInfoVo goblinGoodsInfoVo = goblinRedisUtils.getGoodsInfoVo(spuId);
                for (String skuId : goblinGoodsInfoVo.getSkuIdList()) {
                    GoblinGoodsSkuInfoVo skuInfoVo = goblinRedisUtils.getGoodsSkuInfoVo(skuId);
                    if (skuInfoVo.getErpHosting() == 1) {
                        param.put("warehouse_no", skuInfoVo.getErpWarehouseNo());
                        param.put("spec_no", skuInfoVo.getSkuErpCode());
                        json = erpWdtClient.execute(ErpEnum.WdtAPI.STOCK_QUERY.getUri(), param);
                        ArrayList<SyncStockVo> list = baseStock(json);
                        syncStock(list);
                    }
                }
            } else {
                int pageSize = 40;
                int allCount = (int) mongoTemplate.count(Query.query(Criteria.where("erpHosting").is(1)), GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());//总条数
                int pageCount = (allCount / pageSize) + 1;
                param.put("page_size", pageSize + "");
                for (int i = 0; i < pageCount; i++) {
                    param.put("page_no", i + "");
                    json = erpWdtClient.execute(ErpEnum.WdtAPI.STOCK_QUERY.getUri(), param);
                    ArrayList<SyncStockVo> list = baseStock(json);
                    syncStock(list);
                }
            }
        } catch (Exception e) {
            log.error("调用接口失败 spuId:{},min:{}", spuId, min);
            return ResponseDto.failure();
        }
        return ResponseDto.success();
    }

    private ArrayList<SyncStockVo> baseStock(String json) {
        ArrayList<SyncStockVo> stockMap = ErpObjectUtil.syncStockVoList();
        try {
            StockQueryBaseVo data = JsonUtils.fromJson(json, StockQueryBaseVo.class);
            List<StockQueryVo> stockQueryVos = data.getStocks();
            for (StockQueryVo stockQueryVo : stockQueryVos) {
                try {
                    BigDecimal stockNum = stockQueryVo.getStock_num();//可发库存
                    SyncStockVo vo = SyncStockVo.getNew();
                    vo.setSpecNo(stockQueryVo.getSpec_no());
                    vo.setStockErpNum(stockNum);
                    vo.setWarehouseNo(stockQueryVo.getWarehouse_no());
                    stockMap.add(vo);
                } catch (Exception e) {
                    log.error("解析erp数据失败 内层：{}", stockQueryVo);
                }

            }
        } catch (Exception e) {
            log.error("解析erp数据失败 外层：{}", json);
        }
        return stockMap;
    }

    //同步库存
    private void syncStock(ArrayList<SyncStockVo> stockMap) {
        for (SyncStockVo vo : stockMap) {
            String skuId = "";
            try {
                GoblinGoodsSkuInfoVo skuInfoVo = mongoTemplate.findOne(Query.query(Criteria.where("skuErpCode").is(vo.getSpecNo()).and("erpWarehouseNo").is(vo.getWarehouseNo())), GoblinGoodsSkuInfoVo.class, GoblinGoodsSkuInfoVo.class.getSimpleName());
                int changeStock = vo.getStockErpNum().subtract(BigDecimal.valueOf(skuInfoVo.getSkuStock())).intValue();
                skuId = skuInfoVo.getSkuId();
                //mongo修改
                HashMap<String, Object> map = new HashMap<>();
                map.put("stock", vo.getStockErpNum());
                map.put("skuStock", vo.getStockErpNum());
                BasicDBObject obj = new BasicDBObject("$set", mongoConverter.convertToMongoType(map));
                mongoTemplate.getCollection(GoblinGoodsSkuInfoVo.class.getSimpleName()).updateOne(
                        Query.query(Criteria.where("skuId").is(skuId)).getQueryObject(),
                        obj);
                //sql 当前库存 增加changeStock
                queueUtils.sendMsgByGoblinRedis(MQConst.GoblinQueue.GOBLIN_ORDER_CLOSE.getKey(),
                        SqlMapping.get("goblin_sku.stock", vo.getStockErpNum().intValue(), vo.getStockErpNum().intValue(), LocalDateTime.now(), vo.getSpecNo(), vo.getWarehouseNo()));
                //redis incr 增加changeStock
                int stock = 0;
                if (changeStock > 0) {
                    stock = goblinRedisUtils.incrSkuStock(null, skuId, changeStock);
                } else if (changeStock < 0) {
                    stock = goblinRedisUtils.decrSkuStock(null, skuId, Math.abs(changeStock));
                }
                log.info("skuId:{},库存:{}", skuId, stock);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("同步库存失败 skuId:{},erpSpecNo:{},warehouseNo:{}", skuId, vo.getSpecNo(), vo.getWarehouseNo());
            }
        }
    }

}
