package cn.freemud.service.impl;

import cn.freemud.adapter.ActivityAdapter;
import cn.freemud.adapter.ShoppingCartConvertAdapter;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.constant.ResponseCodeConstant;
import cn.freemud.entities.dto.CouponProductDto;
import cn.freemud.entities.dto.activity.ActivityQueryDto;
import cn.freemud.entities.dto.activity.DiscountSharingDto;
import cn.freemud.entities.dto.calculate.ActivityCalculationDiscountRequestDto;
import cn.freemud.entities.dto.calculate.ActivityCalculationDiscountResponseDto;
import cn.freemud.entities.dto.calculate.CalculationDiscountResult;
import cn.freemud.entities.dto.other.ValidCouponBo;
import cn.freemud.entities.dto.product.CheckCartRequest;
import cn.freemud.entities.dto.shoppingCart.ShoppingCartGoodsDto;
import cn.freemud.entities.vo.*;
import cn.freemud.enums.ActivityChannelEnum;
import cn.freemud.enums.ProductType;
import cn.freemud.enums.ResponseResult;
import cn.freemud.enums.ShoppingCartPromotionEnum;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.redis.RedisCache;
import cn.freemud.service.CommonService;
import cn.freemud.service.ShoppingCartNewService;
import cn.freemud.service.thirdparty.ActivityClient;
import cn.freemud.service.thirdparty.CustomerApplicationClient;
import cn.freemud.utils.PromotionFactory;
import cn.freemud.utils.PropertyConvertUtil;
import cn.freemud.utils.RedisLock;
import cn.freemud.utils.ResponseUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.freemud.api.assortment.datamanager.entity.vo.AssortmentCustomerInfoVo;
import com.freemud.api.assortment.datamanager.enums.IappIdType;
import com.freemud.api.assortment.datamanager.manager.customer.AssortmentCustomerInfoManager;
import com.freemud.api.assortment.datamanager.meal.MealCacheManager;
import com.freemud.api.assortment.datamanager.meal.dto.MealNumberDto;
import com.freemud.application.sdk.api.base.SDKCommonBaseContextWare;
import com.freemud.application.sdk.api.log.ErrorLog;
import com.freemud.application.sdk.api.log.LogThreadLocal;
import com.freemud.application.sdk.api.productcenter.domain.ProductBeanDTO;
import com.freemud.sdk.api.assortment.shoppingcart.constant.CartResponseConstant;
import com.freemud.sdk.api.assortment.shoppingcart.constant.CommonsConstant;
import com.freemud.sdk.api.assortment.shoppingcart.constant.MealClearOperationEnum;
import com.freemud.sdk.api.assortment.shoppingcart.domain.CartParamDto;
import com.freemud.sdk.api.assortment.shoppingcart.enums.BusinessTypeEnum;
import com.freemud.sdk.api.assortment.shoppingcart.service.impl.MealCartBaseServiceImpl;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;


/**
 * All rights Reserved, Designed By www.freemud.com
 *
 * @version V1.0
 * @Title:
 * @Package: cn.freemud.service.impl
 * @Descripttion:
 * @author: cuigenyou
 * @date: 2019/9/4 14:28
 * @Copyright: 2017 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目.
 */
@Service
public class ShoppingCartMealServiceImpl implements ShoppingCartNewService {

    @Autowired
    private MealCartBaseServiceImpl mealCartBaseService;
    @Autowired
    private AssortmentCustomerInfoManager customerInfoManager;
    @Autowired
    private AssortmentSdkService assortmentSdkService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ShoppingCartConvertAdapter shoppingCartConvertAdapter;
    @Autowired
    private MealCacheManager mealCacheManager;
    @Autowired
    private CommonService commonService;
    @Autowired
    private ActivityClient activityClient;
    @Autowired
    private TimeSalePromotionForWcService timeSalePromotionForWcService;
    @Autowired
    private CustomerApplicationClient customerApplicationClient;
    @Autowired
    private ActivityAdapter activityAdapter;

    @Override
    public BaseResponse addGoodsByCard(AddGoodsByWeixinCardRequestVo request) {
        return null;
    }

    @Override
    public BaseResponse addGoods(AddShoppingCartGoodsRequestVo requestVo) {
        // 获取用户信息
        CustomerInfoVo customerInfo = getCustomerInfoVo(requestVo.getSessionId());
        if (customerInfo == null || customerInfo.getMemberId() == null) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        if (StringUtils.isBlank(customerInfo.getTableNumber()) || StringUtils.isBlank(customerInfo.getStoreId()) || StringUtils.isBlank(customerInfo.getPartnerId())) {
            return ResponseUtil.error(ResponseResult.SHOPPING_CART_NO_BIND_TABLE_NUMBER);
        }
//        checkBase(customerInfo);
        String userId = customerInfo.getMemberId();
        String partnerId = customerInfo.getPartnerId();
        String storeId = customerInfo.getStoreId();
        String spuId = requestVo.getSpuId();
        String skuId = requestVo.getSkuId();
        String goodsId = StringUtils.isEmpty(skuId) ? spuId : skuId;
        String tableNumber = customerInfo.getTableNumber();
        String appType = customerInfo.getIappId();
        requestVo.setAppType(appType);
        requestVo.setTableNumber(tableNumber);
        CartGoods cartGoods = ShoppingCartConvertAdapter.convent2CartGoods(requestVo);
        List<Long> productIds = new ArrayList<>();
        String couponCode = requestVo.getCouponCode(); // 商品券和换购券券号
        CouponProductDto couponProductDto = new CouponProductDto();
        //商品skuId或者商品券的商品id
        String spuId2 = spuId;
        if (!spuId.startsWith(CommonsConstant.COUPON_PREFIX)) {
            productIds.add(Long.parseLong(goodsId));
        } else {
            if(StringUtils.isEmpty(couponCode)){
                couponCode = spuId.substring(CommonsConstant.COUPON_PREFIX.length());
            }
            //校验券是否有效
            ValidCouponBo validCouponBo = assortmentSdkService.validCoupon(partnerId, storeId, couponCode, productIds,BusinessTypeEnum.getByType(requestVo.getMenuType()).getCode(), skuId, couponProductDto,cartGoods);
            spuId2 = validCouponBo.getSkuId();
        }
        // 获取商品信息
        List<ProductBeanDTO> productBeanListSpuClass =
                assortmentSdkService.getProductsInfoSdk(partnerId, storeId, Collections.singletonList(spuId2), BusinessTypeEnum.SAAS_WC.getName(), mealCartBaseService);
        if (productBeanListSpuClass == null) {
            return ResponseUtil.error(ResponseResult.SHOPPING_CART_ADD_ERROR);
        }
        //缓存中获取购物车商品信息
        // 注意，围餐和点餐redis数据结构不一样
        List<CartGoods> allCartGoodsList = assortmentSdkService.getShoppingCart(partnerId, storeId, userId, requestVo.getSessionId(), tableNumber, mealCartBaseService,null);
        if (CollectionUtils.isEmpty(allCartGoodsList)) {
            allCartGoodsList = new ArrayList<>();
        }
        ShoppingCartGoodsMealResponseVo responseVo = new ShoppingCartGoodsMealResponseVo();
        // 当添加的商品不是商品券时
        if (!spuId.startsWith(CommonsConstant.COUPON_PREFIX)) {
            //添加非商品券商品
            addNotProductGoods(requestVo, cartGoods, goodsId, userId, responseVo, allCartGoodsList);
        } else {
            // 当商品是商品券，里面会判断如果购物车中已有商品券，会将cartGoods的CartGoodsUid设为null
            this.addProductGoods(requestVo, cartGoods, spuId2, userId, responseVo,
                    spuId, allCartGoodsList, productBeanListSpuClass);
        }
        // 获取当前桌号所有人购物车
        Map<String, List<String>> userCartsMap = mealCartBaseService.getUserCarts(customerInfo.getPartnerId(), customerInfo.getStoreId(), customerInfo.getTableNumber());
        buildMealResponse(requestVo.getOrderType(), customerInfo, userCartsMap, responseVo);
        buildActivityCalculationDiscountResponse(customerInfo.getPartnerId(), customerInfo.getStoreId(), customerInfo.getMemberId(), customerInfo.getWxAppId(), requestVo.getOrderType(), customerInfo.isMemberPaid(), responseVo);
        return ResponseUtil.success(responseVo);
    }

    /**
     * 更新购物车时校验参数并对购物车行加锁
     *
     * @param updateShoppingCartGoodsQtyRequestVo 请求
     * @param assortmentCustomerInfoVo            登录信息
     */
    private BaseResponse doCheckAndLock(UpdateShoppingCartGoodsQtyRequestVo updateShoppingCartGoodsQtyRequestVo, CustomerInfoVo assortmentCustomerInfoVo) {
        Integer carVer = updateShoppingCartGoodsQtyRequestVo.getCarVer();
        if (carVer == null || carVer < 1) {
            return ResponseUtil.error(ResponseResult.SHOPPING_CART_VERSION_ERROR);
        }
        checkBase(assortmentCustomerInfoVo);
        Integer cartVersion = mealCartBaseService.getCartVersion(assortmentCustomerInfoVo.getPartnerId(), assortmentCustomerInfoVo.getStoreId(), assortmentCustomerInfoVo.getTableNumber());
        if (!carVer.equals(cartVersion)) {
            return ResponseUtil.error(ResponseResult.SHOPPING_CART_VERSION_ERROR);
        }
        boolean lock = RedisLock.getInstance(redisCache.getRedisTemplate()).lock(updateShoppingCartGoodsQtyRequestVo.getCartGoodsUid());
        if (!lock) {
            //加锁失败
            return ResponseUtil.error(ResponseResult.SHOPPING_CART_VERSION_ERROR);
        }
        return null;
    }

    @Override
    public BaseResponse updateGoodsQty(UpdateShoppingCartGoodsQtyRequestVo requestVo) {
        CustomerInfoVo customerInfo = getCustomerInfoVo(requestVo.getSessionId());
        customerInfo = test(customerInfo, requestVo.getSessionId());
        ShoppingCartGoodsMealResponseVo responseVo = new ShoppingCartGoodsMealResponseVo();
        // 获取当前桌号所有人购物车
        Map<String, List<String>> userCartsMap = mealCartBaseService.getUserCarts(customerInfo.getPartnerId(), customerInfo.getStoreId(), customerInfo.getTableNumber());

        BaseResponse baseResponse = doCheckAndLock(requestVo, customerInfo);
        if (baseResponse != null) {
            buildMealResponse(requestVo.getOrderType(), customerInfo, userCartsMap, responseVo);
            baseResponse.setResult(responseVo);
            return baseResponse;
        }
        try {
            CartGoods goods = assortmentSdkService.getCartGoodsBySdk(customerInfo.getPartnerId(), customerInfo.getMemberId(),
                    customerInfo.getStoreId(), requestVo.getCartGoodsUid(), customerInfo.getTableNumber(), this.mealCartBaseService,null);
            if (goods == null) {
                doUnlock(requestVo.getCartGoodsUid());
                buildMealResponse(requestVo.getOrderType(), customerInfo, userCartsMap, responseVo);
                return ResponseUtil.error(ResponseResult.SHOPPING_CART_VERSION_ERROR.getCode(), "购物车商品有变动，请手动刷新再修改", responseVo);
            }
            // 更新购物车中数量
            assortmentSdkService.updateGoodsQtyBySdk(customerInfo.getPartnerId(), customerInfo.getMemberId(),
                    customerInfo.getStoreId(), requestVo.getCartGoodsUid(), requestVo.getQty(), customerInfo.getTableNumber(), this.mealCartBaseService,null);
        } catch (Exception e) {
//            ErrorLog.errorConvertJson(SDKCommonBaseContextWare.getAppName(), LogThreadLocal.getTrackingNo(), getClass(), "updateGoodsQty:" + e.getMessage(), e);
            ErrorLog.errorConvertJson(getClass(),"updateGoodsQty:", e);
            return ResponseUtil.error(ResponseResult.SHOPPING_CART_VERSION_ERROR, "购物车商品有变动，请手动刷新再修改");
        } finally {
            doUnlock(requestVo.getCartGoodsUid());
        }

        buildMealResponse(requestVo.getOrderType(), customerInfo, userCartsMap, responseVo);
        buildActivityCalculationDiscountResponse(customerInfo.getPartnerId(), customerInfo.getStoreId(), customerInfo.getMemberId(), customerInfo.getWxAppId(), requestVo.getOrderType(), customerInfo.isMemberPaid(), responseVo);
        return ResponseUtil.success(responseVo);
    }

    //todo 单元测试使用
    private CustomerInfoVo test(CustomerInfoVo customerInfo, String sessionId) {
        if ((customerInfo == null || customerInfo.getMemberId() == null) && (SDKCommonBaseContextWare.getProfile().equals(SDKCommonBaseContextWare.profiles.DEV.getProfile())
                || SDKCommonBaseContextWare.getProfile().equals(SDKCommonBaseContextWare.profiles.DEFAULT.getProfile()))
                && sessionId.startsWith("unitTestMeal")) {
            customerInfo = new CustomerInfoVo();
            customerInfo.setMemberId(sessionId);
            customerInfo.setMobile("10086");
            customerInfo.setNickName("test1864" + sessionId);
            customerInfo.setPartnerId("1864");
            customerInfo.setStoreId("999999998");
            customerInfo.setTableNumber("0032");
            customerInfo.setPhotoUrl("https://picture.sandload.cn/1564990587663.jpg");
            customerInfo.setIappId(IappIdType.WC_XCX.getCode());
        }
        return customerInfo;
    }

    private void doUnlock(String cartGoodsUid) {
        RedisLock.getInstance(redisCache.getRedisTemplate()).unlock(cartGoodsUid);
    }

    @Override
    public BaseResponse getGoodsList(ShoppingCartInfoRequestVo request) {
        CustomerInfoVo customerInfo = getCustomerInfoVo(request.getSessionId());
        customerInfo = test(customerInfo, request.getSessionId());

        checkBase(customerInfo);
        // key sessionId  value cartGoodsIdList
        Map<String, List<String>> userCartsMap = mealCartBaseService.getUserCarts(customerInfo.getPartnerId(), customerInfo.getStoreId(), customerInfo.getTableNumber());
        ShoppingCartGoodsMealResponseVo responseVo = new ShoppingCartGoodsMealResponseVo();
        buildMealResponse(request.getOrderType(), customerInfo, userCartsMap, responseVo);
        buildActivityCalculationDiscountResponse(customerInfo.getPartnerId(), customerInfo.getStoreId(), customerInfo.getMemberId(), customerInfo.getWxAppId(), request.getOrderType(), customerInfo.isMemberPaid(), responseVo);
        return ResponseUtil.success(responseVo);
    }

    @Override
    public BaseResponse getGoodsListCheck(ShoppingCartInfoRequestVo shoppingCartInfoRequestVo) {
        return null;
    }

    private void buildMealResponse(Integer orderType, CustomerInfoVo customerInfo, Map<String, List<String>> userCartsMap, ShoppingCartGoodsMealResponseVo responseVo) {
        responseVo.setCarVer(this.mealCartBaseService.getCartVersion(customerInfo.getPartnerId(), customerInfo.getStoreId(), customerInfo.getTableNumber()));
        if (CollectionUtils.isEmpty(userCartsMap)) {
            return;
        }
        //sessionId为空时，查询所有的
        List<CartGoods> cartGoodsList = assortmentSdkService.getShoppingCart(customerInfo.getPartnerId(), customerInfo.getStoreId(), "", "", customerInfo.getTableNumber(), this.mealCartBaseService,null);
        if (CollectionUtils.isEmpty(cartGoodsList)) {
            return;
        }
        //检查购物车中是否存在非法或者价格变更商品
        CheckCartRequest checkCartRequest = assortmentSdkService.checkShoppingCartSdk(cartGoodsList, customerInfo.getPartnerId(), customerInfo.getStoreId(), responseVo, orderType, customerInfo.getTableNumber(), BusinessTypeEnum.SAAS_WC.getName(),this.mealCartBaseService);
        if (checkCartRequest != null) {
            if (checkCartRequest.getShoppingCartGoodsResponseVo() != null && StringUtils.isNotBlank(checkCartRequest.getShoppingCartGoodsResponseVo().getToastMsg())) {
                responseVo.setToastMsg(checkCartRequest.getShoppingCartGoodsResponseVo().getToastMsg());
                responseVo.setChanged(true);
            }
            cartGoodsList = JSONArray.parseArray(JSONObject.toJSONString(checkCartRequest.getCartGoodsList()), CartGoods.class);
        }
        if (!CollectionUtils.isEmpty(cartGoodsList)) {
            //组装返回结果
            buildResponse(responseVo, userCartsMap, cartGoodsList, customerInfo.getMemberId());
        }

        //获取点餐人数和餐具
        MealNumberDto dinnerNumber = mealCacheManager.getDinnerNumber(customerInfo.getPartnerId(), customerInfo.getStoreId(), customerInfo.getTableNumber());
        if (dinnerNumber != null && dinnerNumber.getUnitPrice() != null) {
            responseVo.setPeopleNumber(dinnerNumber.getPeopleNumber());
            responseVo.setMealPrice(dinnerNumber.getUnitPrice());
        }

    }


    /**
     * 组装返回数据结构
     *
     * @param responseVo    返回response
     * @param userCartsMap  购物车人员及购物车id集合
     * @param cartGoodsList 购物车商品集合
     */
    private void buildResponse(ShoppingCartGoodsMealResponseVo responseVo, Map<String, List<String>> userCartsMap, List<CartGoods> cartGoodsList, String memberId) {
        List<ShoppingCartGoodsMealCartVo> cartList = new ArrayList<>(userCartsMap.size());
        Map<String, CartGoods> cartGoodsMap = cartGoodsList.stream().collect(Collectors.toMap(CartGoods::getCartGoodsUid, each -> each, (k1, k2) -> k1));
        //按照人员构建购物车商品列表
        buildCartList(cartList, userCartsMap, cartGoodsMap, memberId);
        cartList.sort(Comparator.comparing(ShoppingCartGoodsMealCartVo::isCurrentUser).reversed().thenComparing(ShoppingCartGoodsMealCartVo::getMemberId));
        responseVo.setCartList(cartList);
    }

    /**
     * 按照个人组装商品列表
     *
     * @param cartGoodsList 围餐购物车返回结果
     * @param userCartsMap  购物车人员及购物车id集合
     * @param cartGoodsMap  购物车商品集合
     */
    private void buildCartList(List<ShoppingCartGoodsMealCartVo> cartGoodsList, Map<String, List<String>> userCartsMap, Map<String, CartGoods> cartGoodsMap, String memberId) {
        userCartsMap.forEach((sessionId, cartIdList) ->
                addCartGoodsListBySessionId(cartGoodsList, cartGoodsMap, sessionId, cartIdList, memberId)
        );
    }

    private void addCartGoodsListBySessionId(List<ShoppingCartGoodsMealCartVo> cartGoodsList, Map<String, CartGoods> cartGoodsMap, String sessionId, List<String> cartIdList, String loginMemberId) {
        CustomerInfoVo customerInfo = getCustomerInfoVo(sessionId);
        customerInfo = test(customerInfo, sessionId);
        if (customerInfo == null || StringUtils.isEmpty(customerInfo.getMemberId()) || CollectionUtils.isEmpty(cartIdList)) {
            return;
        }
        String memberId = customerInfo.getMemberId();
        List<CartGoods> products;

        Optional<ShoppingCartGoodsMealCartVo> mealCartVoOptional = cartGoodsList.stream().filter(eachMealCart -> eachMealCart.getMemberId().equals(memberId)).findAny();
        if (mealCartVoOptional.isPresent()) {
            ShoppingCartGoodsMealCartVo shoppingCartGoodsMealCartVo = mealCartVoOptional.get();
            products = shoppingCartGoodsMealCartVo.getProducts();
            Integer singleTotalNumber = buildProduct(cartGoodsMap, cartIdList, products);
            shoppingCartGoodsMealCartVo.setProducts(products);
            shoppingCartGoodsMealCartVo.setSingleTotalNumber(shoppingCartGoodsMealCartVo.getSingleTotalNumber() + singleTotalNumber);
        } else {
            products = new ArrayList<>(cartIdList.size());
            //组装商品列表
            Integer singleTotalNumber = buildProduct(cartGoodsMap, cartIdList, products);
            //如果商品列表为空，则不显示
            if (CollectionUtils.isEmpty(products)) {
                return;
            }
            ShoppingCartGoodsMealCartVo mealCartVo = new ShoppingCartGoodsMealCartVo();
            mealCartVo.setCurrentUser(loginMemberId.equals(memberId));
            mealCartVo.setMemberId(memberId);
            mealCartVo.setUserName(customerInfo.getNickName());
            mealCartVo.setMobile(customerInfo.getMobile());
            mealCartVo.setHeaderImg(customerInfo.getPhotoUrl());
            mealCartVo.setSingleTotalNumber(singleTotalNumber);
            mealCartVo.setProducts(products);
            cartGoodsList.add(mealCartVo);
        }
    }

    /**
     * 组装商品列表
     *
     * @param cartGoodsMap 购物车商品集合
     * @param cartIdList   个人购物车行集合
     * @param products     个人商品列表集合
     * @return 商品数量
     */
    private Integer buildProduct(Map<String, CartGoods> cartGoodsMap, List<String> cartIdList, List<CartGoods> products) {
        //商品计数器
        Integer singleTotalNumber = 0;
        for (String cartGoodsId : cartIdList) {
            CartGoods cartGoods = cartGoodsMap.get(cartGoodsId);
            if (cartGoods == null) {
                continue;
            }
            //如果存在相同商品合并
            singleTotalNumber += cartGoods.getQty();
            addOrUpdate(products, cartGoods);
        }
        products.sort((p1, p2) -> (int) (p1.getCreateTimeMili() - p2.getCreateTimeMili()));
        return singleTotalNumber;
    }


    /**
     * 拉取购物车去下单整合商品
     *
     * @param cartGoodsList 购物车商品列表
     * @param products      最终返回商品列表
     */
    private void buildProduct(List<CartGoods> cartGoodsList, List<ShoppingCartGoodsDto.CartGoodsDetailDto> products) {
        List<CartGoods> collectCartGoods = new ArrayList<>();
        cartGoodsList.forEach(each -> addOrUpdate(collectCartGoods, each));
        collectCartGoods.forEach(eachGoods -> {
            ShoppingCartGoodsDto.CartGoodsDetailDto cartGoodsDetailDto = shoppingCartConvertAdapter.convertCartGoods2DetailGoods(eachGoods, new ArrayList<>(), new HashMap<>());
            int totalDiscountAmount = (eachGoods.getOriginalPrice().intValue() - eachGoods.getFinalPrice().intValue()) * cartGoodsDetailDto.getQty();
            if(Objects.equals(cartGoodsDetailDto.getProductType(), ProductType.SETMEAL.getCode())) {
                int discountAmount = (eachGoods.getOriginalPrice().intValue() - eachGoods.getFinalPrice().intValue()) * eachGoods.getQty();
                int productGroupDiscountAmount = eachGoods.getProductGroupList().stream().mapToInt(t -> t.getFinalPrice().intValue() * t.getQty()).sum();
                totalDiscountAmount = discountAmount - productGroupDiscountAmount * eachGoods.getQty();
            }
            cartGoodsDetailDto.setTotalDiscountAmount(totalDiscountAmount);

            List<ShoppingCartGoodsDto.CartGoodsDetailDto> cartGoodsDetailDtos = new ArrayList<>();
            cartGoodsDetailDtos.addAll(shoppingCartConvertAdapter.getComboxGoods2DetailGoods(eachGoods, eachGoods.getProductComboList(), true,totalDiscountAmount));
            cartGoodsDetailDtos.addAll(shoppingCartConvertAdapter.getComboxGoods2DetailGoods(eachGoods, eachGoods.getProductGroupList(), false,0));
            cartGoodsDetailDto.setComboProducts(cartGoodsDetailDtos);
            cartGoodsDetailDto.setOriginalProductType(eachGoods.getOriginalProductType());
            products.add(cartGoodsDetailDto);
        });
    }

    private void buildActivityCalculationDiscountResponse(String partnerId, String storeId, String userId, String appId, Integer orderType, boolean isMember, ShoppingCartGoodsMealResponseVo shoppingCartGoodsResponseVo) {

        ActivityQueryDto activityQueryDto = activityAdapter.getActivityQueryDto(partnerId, storeId, userId, appId, orderType);
        // 封装满减优惠规则信息
        FullPromotionService fullPromotionService = (FullPromotionService) PromotionFactory.getPromotionService(ShoppingCartPromotionEnum.FULL_REDUCTION);
        ShoppingCartGoodsResponseVo shoppingCartGoodsResponseVos  =new ShoppingCartGoodsResponseVo();
        fullPromotionService.updateShoppingCartGoodsDiscount(null, activityQueryDto, null, null, shoppingCartGoodsResponseVos, null, null);
        shoppingCartGoodsResponseVo.setActivityTip(shoppingCartGoodsResponseVos.getActivityTip());

        if(CollectionUtils.isEmpty(shoppingCartGoodsResponseVo.getCartList())) {
            return;
        }
        List<CartGoods> cartGoodsList = shoppingCartGoodsResponseVo.getCartList().stream().flatMap(t -> t.getProducts().stream()).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(cartGoodsList)) {
            return;
        }
        DiscountSharingDto discountSharingDto = new DiscountSharingDto();
        CalculationDiscountResult calculationDiscountResult = this.getActivityCalculationDiscountResponse(partnerId, storeId, userId, appId, orderType, isMember, cartGoodsList, new ArrayList<>(), new ArrayList<>(), BusinessTypeEnum.SAAS_MALL.getCode(), 0L,null, null,0L,discountSharingDto);
        if(calculationDiscountResult == null) {
            return;
        }
        // 限时特价
        timeSalePromotionForWcService.updateShoppingCartGoodsDiscount(calculationDiscountResult, cartGoodsList, shoppingCartGoodsResponseVo);
    }

    /**
     * 如果存在相同商品合并
     *
     * @param products  最终返回商品列表
     * @param eachGoods 当前商品
     */
    private void addOrUpdate(List<CartGoods> products, CartGoods eachGoods) {
        int index = products.indexOf(eachGoods);

        if (index > -1 && !eachGoods.hasWeight()) {
            CartGoods tmp = products.get(index);
            eachGoods.setQty(tmp.getQty() + eachGoods.getQty());
            products.remove(tmp);
        }
        if (eachGoods.hasWeight()) {
            eachGoods.setWeightType(true);
        }
        products.add(eachGoods);
    }

    @Override
    public BaseResponse clear(ShoppingCartClearRequestVo request) {

        CustomerInfoVo customerInfo = null;
        boolean posClear;

        Integer operationType = request.getOperationType();
        if (operationType == null) {
            return ResponseUtil.error(ResponseResult.PARAMETER_MISSING, "operationType不能为空");
        }
        MealClearOperationEnum operation = MealClearOperationEnum.getByCode(operationType);
        if (operation == null) {
            return ResponseUtil.error(ResponseResult.PARAMETER_MISSING, "不识别的operationType值");
        }
        if (StringUtils.isEmpty(request.getSessionId())) {
            if (!operationType.equals(MealClearOperationEnum.CLEAR_ALL.getOperationType())) {
                return ResponseUtil.error(ResponseResult.PARAMETER_MISSING, "不识别的operationType值");
            }
            posClear = true;
        } else {
            customerInfo = getCustomerInfoVo(request.getSessionId());
            customerInfo = test(customerInfo, request.getSessionId());
            checkBase(customerInfo);
            posClear = false;
        }

        CartParamDto cartParamDto = new CartParamDto();
        cartParamDto.setPartnerId(posClear ? request.getPartnerId() : customerInfo.getPartnerId());
        cartParamDto.setStoreId(posClear ? request.getShopId() : customerInfo.getStoreId());
        cartParamDto.setTableNumber(posClear ? request.getTableNumber() : customerInfo.getTableNumber());
        cartParamDto.setOperationType(operation);
        BaseResponse clearResult = mealCartBaseService.clear(cartParamDto, LogThreadLocal.getTrackingNo());
        if (clearResult == null) {
            return ResponseUtil.error(ResponseResult.OPERATE_TOO_OFTEN);
        }
        if (clearResult.getCode().equals(CartResponseConstant.FAIL.getCode())) {
            return ResponseUtil.error(ResponseResult.OPERATE_TOO_OFTEN, clearResult.getMessage());
        }

        return ResponseUtil.success();
    }

    @Override
    public BaseResponse<ShoppingCartGoodsDto> getShoppingCartGoods(ShoppingCartInfoRequestVo shoppingCartInfoRequestVo, CreateOrderVo.PremiumExchangeActivity premiumExchangeActivity) {

        CustomerInfoVo customerInfo = getCustomerInfoVo(shoppingCartInfoRequestVo.getSessionId());

        customerInfo = test(customerInfo, shoppingCartInfoRequestVo.getSessionId());

        checkBase(customerInfo);
        String partnerId = customerInfo.getPartnerId();
        String storeId = customerInfo.getStoreId();
        String tableNumber = customerInfo.getTableNumber();
        Integer carVer = shoppingCartInfoRequestVo.getCarVer();
        ShoppingCartGoodsDto result = new ShoppingCartGoodsDto();
        Integer cartVersion = this.mealCartBaseService.getCartVersion(partnerId, storeId, tableNumber);
        result.setCarVer(cartVersion);
        BaseResponse check = checkToOrder(partnerId, storeId, tableNumber, carVer, cartVersion);
        if (check != null) {
            check.setResult(result);
            return check;
        }
        //sessionId为空时，查询所有的
        List<CartGoods> cartGoodsList = assortmentSdkService.getShoppingCart(customerInfo.getPartnerId(), customerInfo.getStoreId(), customerInfo.getMemberId(), "", customerInfo.getTableNumber(), this.mealCartBaseService,null);
        if (CollectionUtils.isEmpty(cartGoodsList)) {
            return ResponseUtil.error(ResponseResult.SHOPPING_CART_ADD_INVAILD, result);
        }
        //锁定当前所有购物车行
        this.mealCartBaseService.lockCart(partnerId, storeId, tableNumber, cartGoodsList.stream().map(CartGoods::getCartGoodsUid).collect(Collectors.toList()));
        //检查购物车中是否存在非法或者价格变更商品
        CheckCartRequest checkCartRequest = assortmentSdkService.checkShoppingCartSdk(cartGoodsList, customerInfo.getPartnerId(), customerInfo.getStoreId(), new ShoppingCartGoodsBaseResponseVo(), shoppingCartInfoRequestVo.getOrderType(), customerInfo.getTableNumber(),BusinessTypeEnum.SAAS_WC.getName() ,this.mealCartBaseService);
        if (checkCartRequest != null) {
            if (checkCartRequest.getShoppingCartGoodsResponseVo() != null && StringUtils.isNotBlank(checkCartRequest.getShoppingCartGoodsResponseVo().getToastMsg())) {
                return ResponseUtil.error(ResponseResult.SHOPPING_CART_VERSION_ERROR.getCode(), checkCartRequest.getShoppingCartGoodsResponseVo().getToastMsg(), result);
            }
            cartGoodsList = JSONArray.parseArray(JSONObject.toJSONString(checkCartRequest.getCartGoodsList()), CartGoods.class);
        }
        List<ShoppingCartGoodsDto.CartGoodsDetailDto> products = new ArrayList<>();
        buildProduct(cartGoodsList, products);
        result.setProducts(products);
        result.setCarVer(cartVersion);
        return ResponseUtil.success(result);
    }


    private BaseResponse checkToOrder(String partnerId, String storeId, String tableNumber, Integer carVer, Integer cartVersion) {
        if (carVer == null || carVer < 1) {
            return ResponseUtil.error(ResponseResult.SHOPPING_CART_ADD_INVAILD.getCode(), "carVer版本号错误");
        }
        if (!carVer.equals(cartVersion)) {
            return ResponseUtil.error(ResponseResult.SHOPPING_CART_VERSION_ERROR.getCode(), "购物车商品有变动，请手动刷新再下单");
        }
        List<String> lockCart = this.mealCartBaseService.getLockCart(partnerId, storeId, tableNumber);
        if (!CollectionUtils.isEmpty(lockCart)) {
            return ResponseUtil.error(ResponseResult.SHOPPING_CART_ORDERING);
        }
        return null;
    }

    @Override
    public CalculationDiscountResult getActivityCalculationDiscountResponse(String partnerId, String storeId, String userId, String appId, Integer orderType, boolean isMember,
                                                                            List<CartGoods> cartGoodsList, List<ActivityCalculationDiscountRequestDto.CalculationDiscountCoupon> coupons, List<ShoppingCartInfoRequestVo.SendGoods> sendGoodsList, String menuType, Long distributionFee, Integer bizType, Integer accountFlag, long nightDistributionFee, DiscountSharingDto discountSharingDto) {
        ActivityCalculationDiscountRequestDto activityCalculationDiscountRequestDto = getActivityCalculationDiscountRequestDto(partnerId, storeId, userId, appId, orderType);
        List<ActivityCalculationDiscountRequestDto.CalculationDiscountGoods> calculationDiscountGoodsList = new ArrayList<>();
        cartGoodsList = cartGoodsList.stream().filter(t -> !isWeightProduct(t)).collect(Collectors.toList());
        for (CartGoods cartGoods : cartGoodsList) {
            this.addCalculationDiscountGoods(calculationDiscountGoodsList, cartGoods.getGoodsId(), cartGoods.getQty(), cartGoods.getFinalPrice());
        }
        calculationDiscountGoodsList.removeIf(calculationDiscountGoods -> (calculationDiscountGoods.getGoodsQuantity().equals(0)));
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(calculationDiscountGoodsList)) {
            return null;
        }

        activityCalculationDiscountRequestDto.setGoods(calculationDiscountGoodsList);
        activityCalculationDiscountRequestDto.setCoupons(coupons);
        activityCalculationDiscountRequestDto.setOrgIds(commonService.getOrgIdsForCoupon(partnerId, storeId));
        activityCalculationDiscountRequestDto.setDistributionFee(distributionFee);
        activityCalculationDiscountRequestDto.setNightDistributionFee(nightDistributionFee);
        activityCalculationDiscountRequestDto.setIsMember(isMember);
        ActivityCalculationDiscountResponseDto activityCalculationDiscountResponseDto = activityClient.calculationDiscount(activityCalculationDiscountRequestDto);
//        try {
//            activityCalculationDiscountResponseDto = activityClient.calculationDiscount(activityCalculationDiscountRequestDto);
//        } catch (Exception ex) {
//            ErrorLog.errorDev("500", "calculation_discount_error", ex, activityCalculationDiscountRequestDto);
//            throw new ServiceException(ResponseResult.OPERATE_TOO_OFTEN);
//        }
        // 返回成功
        if (activityCalculationDiscountResponseDto != null && StringUtils.equals(activityCalculationDiscountResponseDto.getStatusCode(), ResponseCodeConstant.RESPONSE_SUCCESS_STR)) {
            CalculationDiscountResult result = activityCalculationDiscountResponseDto.getResult();
            result.setDeliveryAmount(distributionFee);
            result.setDistributionFee(result.getDistributionFee());
            return result;
        }
        throw new ServiceException(ResponseResult.OPERATE_TOO_OFTEN);
    }

    private ActivityCalculationDiscountRequestDto getActivityCalculationDiscountRequestDto(String partnerId, String storeId, String userId, String appId, Integer orderType) {
        ActivityCalculationDiscountRequestDto activityCalculationDiscountRequestDto = new ActivityCalculationDiscountRequestDto();
        activityCalculationDiscountRequestDto.setPartnerCode(partnerId);
        activityCalculationDiscountRequestDto.setStoreId(storeId);
        activityCalculationDiscountRequestDto.setIsShowGoodsActivity(1);
        activityCalculationDiscountRequestDto.setUserId(userId);
        activityCalculationDiscountRequestDto.setVer(1);
        activityCalculationDiscountRequestDto.setAppId(appId);
        ActivityChannelEnum activityChannelEnum = PropertyConvertUtil.orderTypeConvert2ActivityChannel(orderType);
        if (!Objects.isNull(activityChannelEnum)) {
            activityCalculationDiscountRequestDto.setChannel(activityChannelEnum.getCode());
        }
        return activityCalculationDiscountRequestDto;
    }

    private void addCalculationDiscountGoods(List<ActivityCalculationDiscountRequestDto.CalculationDiscountGoods> calculationDiscountGoodsList,
                                             String goodsId, Integer goodsQuantity, Long originalPrice) {
        ActivityCalculationDiscountRequestDto.CalculationDiscountGoods calculationDiscountGoods = new ActivityCalculationDiscountRequestDto.CalculationDiscountGoods();
        calculationDiscountGoods.setGoodsId(goodsId);
        calculationDiscountGoods.setGoodsQuantity(goodsQuantity);
        calculationDiscountGoods.setOriginalPrice(originalPrice);
        this.addCalculationDiscountGoods(calculationDiscountGoodsList, calculationDiscountGoods);
    }

    private void addCalculationDiscountGoods(List<ActivityCalculationDiscountRequestDto.CalculationDiscountGoods> calculationDiscountGoodsList,
                                             ActivityCalculationDiscountRequestDto.CalculationDiscountGoods calculationDiscountGoods) {
        int index;
        // 当商品已存在时,需累加数量
        if ((index = calculationDiscountGoodsList.indexOf(calculationDiscountGoods)) >= 0) {
            ActivityCalculationDiscountRequestDto.CalculationDiscountGoods oldCalculationDiscountGoods = calculationDiscountGoodsList.get(index);
            oldCalculationDiscountGoods.setGoodsQuantity(oldCalculationDiscountGoods.getGoodsQuantity() + calculationDiscountGoods.getGoodsQuantity());
        } else {
            calculationDiscountGoodsList.add(calculationDiscountGoods);
        }
    }

    @Override
    public List<CartGoods> updateCartGoodsLegal(CartGoods cartGoods, String userId, ShoppingCartGoodsBaseResponseVo shoppingCartGoodsResponseVo, AddShoppingCartGoodsRequestVo addShoppingCartGoodsRequestVo, List<CartGoods> oldAllCartGoodsList) {

        CheckCartRequest checkCartRequest = assortmentSdkService.checkShoppingCartSdk(Collections.singletonList(cartGoods), addShoppingCartGoodsRequestVo.getPartnerId(), addShoppingCartGoodsRequestVo.getShopId(), shoppingCartGoodsResponseVo, addShoppingCartGoodsRequestVo.getOrderType(), addShoppingCartGoodsRequestVo.getTableNumber(),BusinessTypeEnum.SAAS_WC.getName() ,this.mealCartBaseService);

        if (checkCartRequest == null) {
            throw new ServiceException(ResponseResult.STORE_ITEM_CHECK_VAILD_ERROR);
        }
        if (CollectionUtils.isEmpty(checkCartRequest.getCartGoodsList())) {
            throw new ServiceException(ResponseResult.STORE_ITEM_NOT_FOUND);
        }

        CartGoods checkGood = JSONArray.parseArray(JSONObject.toJSONString(checkCartRequest.getCartGoodsList()), CartGoods.class).get(0);


        String updateCartGoodId = null;

        //如果不存在称重菜
        if (!checkGood.hasWeight()) {
            //过滤出任意一个匹配的商品
            Optional<CartGoods> optionalGood = oldAllCartGoodsList.stream().filter(each -> each.equals(checkGood)).findAny();
            //如果匹配到相同商品则修改数量
            if (optionalGood.isPresent()) {
                CartGoods optionalCartGood = optionalGood.get();
                updateCartGoodId = optionalCartGood.getCartGoodsUid();
                checkGood.setCartGoodsUid(updateCartGoodId);
                checkGood.setQty(optionalCartGood.getQty() + cartGoods.getQty());
                optionalCartGood.setQty(optionalCartGood.getQty() + cartGoods.getQty());
            }
        }

        com.freemud.sdk.api.assortment.shoppingcart.domain.CartParamDto cartParamDto = new com.freemud.sdk.api.assortment.shoppingcart.domain.CartParamDto();
        cartParamDto.setTableNumber(addShoppingCartGoodsRequestVo.getTableNumber());
        cartParamDto.setSessionId(addShoppingCartGoodsRequestVo.getSessionId());
        cartParamDto.setStoreId(addShoppingCartGoodsRequestVo.getShopId());
        cartParamDto.setPartnerId(addShoppingCartGoodsRequestVo.getPartnerId());

        if (StringUtils.isBlank(updateCartGoodId)) {
            //新增
            com.freemud.sdk.api.assortment.shoppingcart.domain.CartGoods reqCartGoodsVo = JSONObject.parseObject(JSONObject.toJSONString(checkGood), com.freemud.sdk.api.assortment.shoppingcart.domain.CartGoods.class);
            cartParamDto.setCartGoodsList(Collections.singletonList(reqCartGoodsVo));
            this.mealCartBaseService.addCartGoodList(cartParamDto);
            oldAllCartGoodsList.add(checkGood);
        } else {
            // update cartGoods
            cartParamDto.setCartGoodsUid(updateCartGoodId);
            cartParamDto.setQty(checkGood.getQty());
            this.mealCartBaseService.updateGoodsQty(cartParamDto, LogThreadLocal.getTrackingNo());
        }
        return oldAllCartGoodsList;
    }

    @Override
    public BaseResponse getV3Promotion(BaseRequestVo request) {
        return null;
    }


    private void checkBase(CustomerInfoVo assortmentCustomerInfoVo) {
        if (assortmentCustomerInfoVo == null || assortmentCustomerInfoVo.getMemberId() == null) {
            throw new ServiceException(ResponseResult.NOT_LOGIN);
        }
        if (StringUtils.isBlank(assortmentCustomerInfoVo.getTableNumber()) || StringUtils.isBlank(assortmentCustomerInfoVo.getStoreId()) || StringUtils.isBlank(assortmentCustomerInfoVo.getPartnerId())) {
            throw new ServiceException(ResponseResult.SHOPPING_CART_NO_BIND_TABLE_NUMBER);
        }
    }

    private boolean isWeightProduct(CartGoods cartGoods) {
        if (cartGoods.isWeightType()) {
            return true;
        }
        if (!CollectionUtils.isEmpty(cartGoods.getProductComboList())) {
            for (CartGoods.ComboxGoods comboxGoods : cartGoods.getProductComboList()) {
                if (comboxGoods.isWeightType()) {
                    return true;
                }
            }
        }
        return false;
    }

    private CustomerInfoVo getCustomerInfoVo(String sessionId) {
//        GetSessionUserInfoDto getSessionUserInfoDto = new GetSessionUserInfoDto();
//        getSessionUserInfoDto.setIsGetPaid(true);
//        getSessionUserInfoDto.setSessionId(sessionId);
//        BaseResponse<CustomerInfoVo> sessionUserInfo = customerApplicationClient.getSessionUserInfo(getSessionUserInfoDto);
//        if (!ResponseResult.SUCCESS.getCode().equals(sessionUserInfo.getCode()) || sessionUserInfo.getResult() == null) {
//            return null;
//        }
//        return sessionUserInfo.getResult();
        AssortmentCustomerInfoVo customerInfoVo = customerInfoManager.getCustomerInfoByObject(sessionId);
        if(customerInfoVo == null) return null;
        String jsonObject = JSON.toJSONString(customerInfoVo);
        CustomerInfoVo customerInfoVo1 = JSON.parseObject(jsonObject,CustomerInfoVo.class);
//        BeanUtil.convertBean(customerInfoVo,customerInfoVo1);
        return customerInfoVo1;
    }

}
