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

import com.alibaba.fastjson.JSON;
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.param.OrderListParam;
import com.liquidnet.service.erp.param.TradeListParam;
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.erp.vo.TradePushVo;
import com.liquidnet.service.goblin.constant.GoblinRedisConst;
import com.liquidnet.service.goblin.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSkuInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinOrderSkuVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreOrderVo;
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.ObjectUtil;
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.beans.factory.annotation.Value;
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;
    @Value("${liquidnet.erp.wdt.contentSize}")
    private int contentSize;
    @Value("${liquidnet.erp.wdt.redisSize}")
    private int redisSize;
    @Value("${liquidnet.erp.wdt.store.shop_no}")
    private String shopNo;

    @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().intValue());
                map.put("skuStock", vo.getStockErpNum().intValue());
                BasicDBObject obj = new BasicDBObject("$set", mongoConverter.convertToMongoType(map));
                mongoTemplate.getCollection(GoblinGoodsSkuInfoVo.class.getSimpleName()).updateOne(
                        Query.query(Criteria.where("skuId").is(skuId)).getQueryObject(),
                        obj);
                goblinRedisUtils.del(GoblinRedisConst.BASIC_GOODS_SKU.concat(skuId));
                //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());
            }
        }
    }


    @Override
    public ResponseDto<Boolean> pushTrade(String singleId) {
        List<TradeListParam> listOrder = ErpObjectUtil.tradeListParam();
        List<List<String>> orderIdList = CollectionUtil.arrayListListString();
        // 获取 订单id 数据
        if ("".equals(singleId) || null == singleId) {
            for (int i = 0; i < redisSize; i++) {
                List<String> list = goblinRedisUtils.getRange(i);
                orderIdList.add(list);
            }
        } else {
            List<String> a = CollectionUtil.arrayListString();
            a.add(singleId);
            orderIdList.add(a);
        }

        //同步订单
        for (List<String> b : orderIdList) {
            for (String orderId : b) {
                TradeListParam tradeListParam = TradeListParam.getNew();
                GoblinStoreOrderVo orderVo = goblinRedisUtils.getGoblinOrder(orderId);
                List<String> orderSkuIds = orderVo.getOrderSkuVoIds();
                List<OrderListParam> listOrderSku = ErpObjectUtil.orderListParam();
                String warehouseNo = "";
                int erpHosting = 0;
                //配置sku维度数据
                for (String orderSkuId : orderSkuIds) {
                    OrderListParam orderSkuParam = OrderListParam.getNew();
                    GoblinOrderSkuVo orderSkuVo = goblinRedisUtils.getGoblinOrderSkuVo(orderSkuId);
                    if (orderSkuVo.getErpHosting() == 1 && orderSkuVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_2.getValue()) {
                        erpHosting = 1;
                    } else {
                        continue;
                    }
                    orderSkuParam.setOid(orderSkuVo.getOrderSkuId());
                    orderSkuParam.setNum(BigDecimal.valueOf(orderSkuVo.getNum()));
                    orderSkuParam.setPrice(orderSkuVo.getSkuPrice());
                    orderSkuParam.setStatus(ErpEnum.WdtStatus.STATUS_UN_SEND.WdtStatus());
                    orderSkuParam.setRefund_status(0);
                    orderSkuParam.setGoods_id(orderSkuVo.getSpuId());
                    orderSkuParam.setSpec_id(orderSkuVo.getSkuId());
                    orderSkuParam.setGoods_no(orderSkuVo.getSpuErpCode());
                    orderSkuParam.setSpec_no(orderSkuVo.getSkuErpCode());
                    orderSkuParam.setGoods_name(orderSkuVo.getSpuName());
                    orderSkuParam.setAdjust_amount(BigDecimal.ZERO);
                    orderSkuParam.setDiscount(BigDecimal.ZERO);
                    orderSkuParam.setShare_discount(orderSkuVo.getPriceVoucher());
                    warehouseNo = orderSkuVo.getErpWarehouseNo();
                    listOrderSku.add(orderSkuParam);
                }
                //配置订单维度数据
                tradeListParam.setOrder_list(listOrderSku);
                tradeListParam.setTid(orderVo.getOrderCode());
                tradeListParam.setTrade_status(ErpEnum.WdtStatus.STATUS_UN_SEND.WdtStatus());
                tradeListParam.setPay_status(2);
                tradeListParam.setDelivery_term(1);
                tradeListParam.setTrade_time(orderVo.getCreatedAt());
                tradeListParam.setPay_time(orderVo.getPayTime());
                tradeListParam.setBuyer_nick(orderVo.getUserName());
                tradeListParam.setPay_id(orderVo.getPayCode());
                tradeListParam.setReceiver_name(orderVo.getOrderAttrVo().getExpressContacts());
                String[] address = orderVo.getOrderAttrVo().getExpressAddress().split(" ");
                if (address.length > 0) {
                    tradeListParam.setReceiver_province(address[0]);
                }
                if (address.length > 1) {
                    tradeListParam.setReceiver_city(address[1]);
                }
                if (address.length > 2) {
                    tradeListParam.setReceiver_district(address[2]);
                }
                tradeListParam.setReceiver_address(orderVo.getOrderAttrVo().getExpressAddress());
                tradeListParam.setReceiver_mobile(orderVo.getOrderAttrVo().getExpressPhone());
                tradeListParam.setPost_amount(orderVo.getPriceExpress());
                tradeListParam.setExt_cod_fee(BigDecimal.ZERO);
                tradeListParam.setOther_amount(BigDecimal.ZERO);
                tradeListParam.setPaid(orderVo.getPriceActual());
                tradeListParam.setWarehouse_no(warehouseNo);
                if (erpHosting == 1) {
                    listOrder.add(tradeListParam);
                }
            }
            //执行同步订单
            Map<String, String> param = CollectionUtil.linkMapStringString();
            param.put("shop_no", shopNo);
            param.put("trade_list", JSON.toJSONString(listOrder));
            String json = erpWdtClient.execute(ErpEnum.WdtAPI.TRADE_PUSH.getUri(), param);
            TradePushVo data = JsonUtils.fromJson(json, TradePushVo.class);
        }
        return ResponseDto.success();
    }
}
