package cn.freemud.service.impl.calculate;

import cn.freemud.constant.ResponseCodeConstant;
import cn.freemud.entities.dto.CheckSpqInfoRequestDto;
import cn.freemud.entities.dto.CheckSpqInfoResponseDto;
import cn.freemud.entities.dto.calculate.*;
import cn.freemud.entities.dto.shoppingCart.SendPoint;
import cn.freemud.entities.vo.CartGoods;
import cn.freemud.entities.vo.ShoppingCartInfoRequestVo;
import cn.freemud.enums.ActivityChannelEnum;
import cn.freemud.enums.CreateOrderType;
import cn.freemud.enums.GoodsTypeEnum;
import cn.freemud.enums.ResponseResult;
import cn.freemud.interceptor.BizServiceException;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.service.CommonService;
import cn.freemud.service.CouponService;
import cn.freemud.service.active.ActiveFactory;
import cn.freemud.service.active.ActiveService;
import cn.freemud.service.impl.AssortmentSdkService;
import cn.freemud.service.thirdparty.ActivityClient;
import cn.freemud.utils.PropertyConvertUtil;
import cn.freemud.entities.dto.activity.DiscountSharingDto;
import com.freemud.application.sdk.api.log.LogThreadLocal;
import com.freemud.sdk.api.assortment.shoppingcart.constant.CommonsConstant;
import com.freemud.sdk.api.assortment.shoppingcart.enums.BusinessTypeEnum;
import com.freemud.sdk.api.assortment.shoppingcart.service.impl.ShoppingCartBaseServiceImpl;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

//import cn.freemud.service.thirdparty.CalculationClient;

/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @Title: cn.freemud.service.impl.calculate CalculationSharingDiscountServiceImpl
 * @Description: 对接促销新的算价服务
 * @author: family
 * @date: 2020/9/4
 * @Copyright: www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */
@Service
public class CalculationSharingDiscountService {

    @Autowired
    private CouponService couponService;
    @Autowired
    private AssortmentSdkService assortmentSdkService;
    @Autowired
    private ShoppingCartBaseServiceImpl shoppingCartBaseService;
    @Autowired
    private CommonService commonService;
    @Autowired
    private ActivityClient activityClient;
    @Autowired
    private ActiveFactory activeFactory;



    public CalculationSharingDiscountService() {
    }


    // 新算价
    public CalculationDiscountResult getCalculationSharingDiscountResult(String menuType
            , String partnerId, String storeId, String userId, String appId, Integer orderType, boolean isMember
            , List<CartGoods> cartGoodsList, List<ActivityCalculationDiscountRequestDto.CalculationDiscountCoupon> coupons
            , List<ShoppingCartInfoRequestVo.SendGoods> sendGoodsList, Long deliveryAmount
            , ShoppingCartInfoRequestVo shoppingCartInfoRequestVo, Integer bizType, Integer accountFlag, DiscountSharingDto sharingDto) {

        ActivityCalculationDiscountRequestDto calculationSharingDiscountRequestDto = this.commonSharingDto(partnerId, storeId, userId, appId, orderType);
        calculationSharingDiscountRequestDto.setTrackingNo(Objects.nonNull(shoppingCartInfoRequestVo) ?
                StringUtils.isNotBlank(shoppingCartInfoRequestVo.getTrackingNo()) ? shoppingCartInfoRequestVo.getTrackingNo() : LogThreadLocal.getTrackingNo()
                : LogThreadLocal.getTrackingNo());
        // 校验后有效的商品券map
        HashMap<String, CheckSpqInfoResponseDto> validCouponMap = new HashMap<>(16);
        List<ActivityCalculationDiscountRequestDto.CalculationDiscountGoods> calculationDiscountGoodsList = new ArrayList<>();
        int cartSize = cartGoodsList.size() - 1;
        HashMap<String, List<String>> spqIdToCartUuid = new HashMap<>(16);
        for (int i = cartSize; i >= 0; i--) {
            CartGoods cartGoods = cartGoodsList.get(i);

            //套餐商品的固定和可选商品必有一个
            if (GoodsTypeEnum.SET_MEAL_GOODS.getGoodsType().equals(cartGoods.getGoodsType())) {
                if (CollectionUtils.isEmpty(cartGoods.getProductGroupList()) && CollectionUtils.isEmpty(cartGoods.getProductComboList())) {
                    cartGoodsList.remove(i);
                    assortmentSdkService.setShoppingCart(partnerId, storeId, userId, cartGoodsList, null, null, this.shoppingCartBaseService,bizType);
                    throw new ServiceException(ResponseResult.SHOPPING_CART_NO_MEAL);
                }
            }
            String couponCode = cartGoods.getCouponCode();
            if (cartGoods.getCartGoodsUid().startsWith(CommonsConstant.COUPON_PREFIX)) {
                couponCode = cartGoods.getCartGoodsUid().substring(CommonsConstant.COUPON_PREFIX.length());
            }
            if (StringUtils.isBlank(couponCode)) {//非商品券
                this.setCommonDiscountGoods(calculationDiscountGoodsList, cartGoods);
                continue;
            }else {
            //商品券->商品券ID换取商品
            CheckSpqInfoRequestDto checkSpqInfoRequestDto = new CheckSpqInfoRequestDto(partnerId, storeId, couponCode, menuType,cartGoods);
            CheckSpqInfoResponseDto checkSpqInfo = null;
                boolean viewProductName = false;
            if (GoodsTypeEnum.HG_COUPON_GOODS.getGoodsType().equals(cartGoods.getGoodsType())
                    || GoodsTypeEnum.BUY_M_SEND_N_COUPON.getGoodsType().equals(cartGoods.getGoodsType())) {
                    checkSpqInfo = couponService.checkSpqInfo(checkSpqInfoRequestDto, cartGoods.getSkuId());
                viewProductName = true;
            } else {
                checkSpqInfo = couponService.checkSpqInfo(checkSpqInfoRequestDto,cartGoods.getSkuId());
            }
            if (null == checkSpqInfo) {
                cartGoodsList.remove(i);
                assortmentSdkService.setShoppingCart(partnerId, storeId, userId, cartGoodsList, null, null, this.shoppingCartBaseService,bizType);
                continue;
                //跑业务异常 商品券不存
            }
            if (cartGoods.getCartGoodsUid().startsWith(CommonsConstant.COUPON_PREFIX)) {
                validCouponMap.put(couponCode, checkSpqInfo);
            }
            if (!GoodsTypeEnum.BUY_M_SEND_N_COUPON.getGoodsType().equals(cartGoods.getGoodsType())) {
                validCouponMap.put(couponCode + checkSpqInfo.getSkuId(), checkSpqInfo);
                validCouponMap.put(couponCode, checkSpqInfo);
            }

            if (spqIdToCartUuid.containsKey(couponCode)) {
                List<String> uuidList = spqIdToCartUuid.get(couponCode);
                uuidList.add(cartGoods.getCartGoodsUid());
                spqIdToCartUuid.put(couponCode, uuidList);
            } else {
                List<String> uuidList = new ArrayList<>();
                uuidList.add(cartGoods.getCartGoodsUid());
                spqIdToCartUuid.put(couponCode, uuidList);
            }
            if (viewProductName) {
                cartGoods.setName(checkSpqInfo.getSkuName());
                cartGoods.setSpuName(checkSpqInfo.getSkuName());
                cartGoods.setSkuName(checkSpqInfo.getSkuName());
            }
            else {
                cartGoods.setName(checkSpqInfo.getCouponName());
                cartGoods.setSpuName(checkSpqInfo.getCouponName());
            }
            cartGoods.setStockLimit(checkSpqInfo.isStockLimit());
            //买M送N券不赋值券名称
            if (GoodsTypeEnum.BUY_M_SEND_N_COUPON.getGoodsType().equals(cartGoods.getGoodsType())) {
                cartGoods.setName(checkSpqInfo.getSkuName());
                cartGoods.setSpuName(checkSpqInfo.getSpuName());
            }
            ActivityCalculationDiscountRequestDto.CalculationDiscountCoupon coupon = new ActivityCalculationDiscountRequestDto.CalculationDiscountCoupon();
            coupon.setCode(checkSpqInfo.getCouponCode());
            coupon.setActivityCode(checkSpqInfo.getActiveCode());
            ActivityCalculationDiscountRequestDto.CalculationDiscountCoupon calculationDiscountCoupon = coupons.stream().filter(p -> coupon.getActivityCode().equals(p.getActivityCode()) && coupon.getCode().equals(p.getCode())).findFirst().orElse(null);
                // 0是非结算页，1为结算页
                accountFlag = accountFlag == null ? 0 : accountFlag;
            if (calculationDiscountCoupon == null) {
                if (GoodsTypeEnum.BUY_M_SEND_N_COUPON.getGoodsType().equals(cartGoods.getGoodsType()) && accountFlag == 1 ){
                    if (cartGoods.getCanUseCoupon() == 0) {
                        coupons.add(coupon);
                    }
                } else {
                    coupons.add(coupon);
                }
            }
            // 添加商品券代表的商品放入促销
            String goodsId = StringUtils.isNotBlank(checkSpqInfo.getSkuId()) ? checkSpqInfo.getSkuId() : checkSpqInfo.getSpuId();
            this.setSpqDiscountGoods(calculationDiscountGoodsList, cartGoods, goodsId, checkSpqInfo.getPrice(), couponCode);
            }
        }

        /*加价购商品不为空*/
        if (CollectionUtils.isNotEmpty(sendGoodsList)) {
            String activityCode = "";
            List<ActivityCalculationDiscountRequestDto.CalculationSendGoodsReqVO> sends = new ArrayList<>();
            List<ActivityCalculationDiscountRequestDto.CalculationActivityReqVO> selectActivityLists = new ArrayList<>();
            ActivityCalculationDiscountRequestDto.CalculationActivityReqVO calculationActivityReqVO = new ActivityCalculationDiscountRequestDto.CalculationActivityReqVO();
            for (ShoppingCartInfoRequestVo.SendGoods send : sendGoodsList) {
                ActivityCalculationDiscountRequestDto.CalculationSendGoodsReqVO reqs = new ActivityCalculationDiscountRequestDto.CalculationSendGoodsReqVO();
                reqs.setGoodsId(send.getGoodsId());
                reqs.setGoodsQuantity(send.getQty());
                reqs.setOriginalPrice(send.getOriginalPrice().intValue());
                reqs.setNowPrice(send.getOriginalPrice().intValue());
                sends.add(reqs);
                activityCode = send.getActivityCode();
            }
            calculationActivityReqVO.setActivityCode(activityCode);
            calculationActivityReqVO.setSendGoods(sends);
            selectActivityLists.add(calculationActivityReqVO);
            calculationSharingDiscountRequestDto.setSelectActivityList(selectActivityLists);
        }

        //剔除商品数量为空的
        calculationDiscountGoodsList.removeIf(v -> v.getGoodsQuantity().equals(0));
        if (CollectionUtils.isEmpty(calculationDiscountGoodsList)) {
            //throw new BizServiceException(ResponseResult.SHOPPING_CART_COUPON_NOT_EXIST,"参数促销计算商品有异常");
            return null;
        }

        //组装促销
        calculationSharingDiscountRequestDto.setGoods(calculationDiscountGoodsList);
        calculationSharingDiscountRequestDto.setCoupons(coupons);
        calculationSharingDiscountRequestDto.setOrgIds(commonService.getOrgIdsForCoupon(partnerId, storeId));
        calculationSharingDiscountRequestDto.setDistributionFee(deliveryAmount);
        calculationSharingDiscountRequestDto.setIsMember(isMember);
        // 构建买一送一寄杯活动用户选择信息
        ActiveService activeService = activeFactory.getBuildChooseGoodsService(partnerId);
        activeService.buildChooseGoodsService(calculationSharingDiscountRequestDto, shoppingCartInfoRequestVo == null ? null : shoppingCartInfoRequestVo.getChooseGoods());
        if(sharingDto != null){
            calculationSharingDiscountRequestDto.setAutoCoupon(sharingDto.getAutoCoupon());
        }
        //算价
        ActivityCalculationDiscountResponseDto sharingDiscountResponseDto = activityClient.calculationSharingDiscount(calculationSharingDiscountRequestDto);
        if(sharingDiscountResponseDto == null){
            throw new ServiceException(ResponseResult.OPERATE_TOO_OFTEN);
        }
        // 返回成功
        if (sharingDiscountResponseDto != null && StringUtils.equals(sharingDiscountResponseDto.getStatusCode(), ResponseCodeConstant.RESPONSE_SUCCESS_STR)) {
            CalculationDiscountResult result = sharingDiscountResponseDto.getResult();

            List<Integer> activityTypes = result.getDiscounts().stream().map(Discount::getType).collect(Collectors.toList());
            if (activityTypes.contains(221)) {
                Discount discountDTO = result.getDiscounts().stream().filter(d -> 221 == d.getType()).findFirst().get();
                convert2SendPoint(result, discountDTO);
            }

            result.setValidCouponMap(validCouponMap);
            result.setSpqIdToCartUuid(spqIdToCartUuid);
            // fisherman  这里传递过来的 配送费 是否要计算一下 配送券的逻辑
            result.setDeliveryAmount(deliveryAmount);
            result.setDistributionFee(result.getDistributionFee());
            return result;
        }

        // 这个是专门给coco使用的券验证错误的异常，message要抛出去
        if (sharingDiscountResponseDto != null && StringUtils.equals(sharingDiscountResponseDto.getStatusCode(), ResponseCodeConstant.COCO_RESPONSE_COUPON_ERR_STR)) {
            throw new BizServiceException(ResponseResult.COCO_COUPON_VALIDATOR_FAIL, sharingDiscountResponseDto.getMsg());
        }

        // 支付宝华莱士紧急修改代码，当促销返回103错误码时，需要报券不适用于该门店，且清空购物车
        //throw new ServiceException(ResponseResult.OPERATE_TOO_OFTEN);
        return null;
    }

    private void convert2SendPoint(CalculationDiscountResult result, Discount discountDTO) {
        SendPoint sendPointNew = new SendPoint();

        SendPointDto sendPointVo = discountDTO.getSendPointVo();
        if (sendPointVo != null) {
            sendPointNew.setMaxNum(sendPointVo.getMaxNum());
            sendPointNew.setSendPoint(sendPointVo.getSendPoint());
            sendPointNew.setValidityDateDays(sendPointVo.getValidityDateDays());
            sendPointNew.setActivityCode(discountDTO.getActivityCode());
            sendPointNew.setEndTime(discountDTO.getEndTime());
            sendPointNew.setStoreLevel(sendPointVo.getStoreLevel());
            sendPointNew.setIsContinueExchange(sendPointVo.getIsContinueExchange());
            result.setSendPointVo(sendPointNew);
        }

    }

    /**
     * 实物商品
     *
     * @param calculationDiscountGoodsList
     * @param cartGoods
     */
    private void setCommonDiscountGoods(List<ActivityCalculationDiscountRequestDto.CalculationDiscountGoods> calculationDiscountGoodsList
            , CartGoods cartGoods) {

        ActivityCalculationDiscountRequestDto.CalculationDiscountGoods calculationDiscountGoods = new ActivityCalculationDiscountRequestDto.CalculationDiscountGoods();
        calculationDiscountGoods.setGoodsId(cartGoods.getGoodsId());
        calculationDiscountGoods.setCartGoodsUid(cartGoods.getCartGoodsUid());
        calculationDiscountGoods.setGoodsQuantity(cartGoods.getQty());
        calculationDiscountGoods.setAddCartTime(cartGoods.getAddCartTime() == null ? 0 : cartGoods.getAddCartTime());
        //if (cartGoods.getGoodsType().equals(GoodsTypeEnum.SET_MEAL_GOODS))
        if (CollectionUtils.isNotEmpty(cartGoods.getProductGroupList()) || CollectionUtils.isNotEmpty(cartGoods.getProductComboList())) {
            calculationDiscountGoods.setOriginalPrice(cartGoods.getFinalPrice() != null ? cartGoods.getFinalPrice() : cartGoods.getOriginalPrice());
        } else {
            calculationDiscountGoods.setOriginalPrice(cartGoods.getOriginalPrice());
        }
        calculationDiscountGoods.setMemberDiscount(cartGoods.getMemberDiscount());
        calculationDiscountGoods.setSpuId(cartGoods.getSpuId());
        //商品加料
        if (CollectionUtils.isNotEmpty(cartGoods.getProductMaterialList())) {
            ArrayList<ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.Material> materials = new ArrayList<>();
            for (CartGoods.MaterialGoods materialGoods : cartGoods.getProductMaterialList()) {
                ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.Material material = new ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.Material();
                material.setType(1);
                material.setGoodsId(materialGoods.getSpuId());
                material.setGoodsQuantity(materialGoods.getQty());
                material.setOriginalPrice(materialGoods.getFinalPrice());
                materials.add(material);
            }
            calculationDiscountGoods.setSmallMaterial(materials);
        }
        //商品组或是套餐或是固定搭配
        if (CollectionUtils.isNotEmpty(cartGoods.getProductComboList())) {
            ArrayList<ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.GroupCombox> groupBoxes = new ArrayList<>();
            for (CartGoods.ComboxGoods boxes : cartGoods.getProductComboList()) {
                ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.GroupCombox combo = new ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.GroupCombox();
                combo.setGoodsId(boxes.getGoodsId());
                combo.setGoodsQuantity(boxes.getQty());
                combo.setOriginalPrice(boxes.getOriginalPrice().intValue());
                groupBoxes.add(combo);
            }
            calculationDiscountGoods.setMeal(true);
            calculationDiscountGoods.setGroupCombox(groupBoxes);
            calculationDiscountGoods.setOriginalPrice(cartGoods.getFinalPrice());
        }

        //可选搭配
        if (CollectionUtils.isNotEmpty(cartGoods.getProductGroupList())) {
            ArrayList<ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.Material> groups = new ArrayList<>();
            for (CartGoods.ComboxGoods group : cartGoods.getProductGroupList()) {
                ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.Material material = new ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.Material();
                material.setType(2);
                material.setGoodsId(group.getGoodsId());
                material.setGoodsQuantity(group.getQty());
                material.setOriginalPrice(group.getFinalPrice());
                groups.add(material);
            }
            calculationDiscountGoods.setSmallMaterial(groups);
        }

        calculationDiscountGoodsList.add(calculationDiscountGoods);
    }

    /**
     * 组队券码商品
     *
     * @param calculationDiscountGoodsList
     * @param cartGoods
     * @param goodsId
     * @param originalPrice
     */
//    private void setSpqDiscountGoods(List<ActivityCalculationDiscountRequestDto.CalculationDiscountGoods> calculationDiscountGoodsList
//            , CartGoods cartGoods, String goodsId, Long originalPrice) {
//        ActivityCalculationDiscountRequestDto.CalculationDiscountGoods calculationDiscountGoods = new CalculationSharingDiscountRequestDto.CalculationDiscountGoods();
//        calculationDiscountGoods.setGoodsId(goodsId);
//        calculationDiscountGoods.setCartGoodsUid(cartGoods.getCartGoodsUid());
//        calculationDiscountGoods.setAddCartTime(cartGoods.getAddCartTime() == null ? 0 : cartGoods.getAddCartTime());
//        calculationDiscountGoods.setGoodsQuantity(cartGoods.getQty());
//        calculationDiscountGoods.setOriginalPrice(originalPrice);
//        calculationDiscountGoods.setMemberDiscount(100);
//        this.setCalculationDiscountGoods(calculationDiscountGoodsList, calculationDiscountGoods);
//    }

    private void setSpqDiscountGoods(List<ActivityCalculationDiscountRequestDto.CalculationDiscountGoods> calculationDiscountGoodsList
            , CartGoods cartGoods
            , String goodsId
            , Long originalPrice
            , String couponCode) {
        ActivityCalculationDiscountRequestDto.CalculationDiscountGoods calculationDiscountGoods = new ActivityCalculationDiscountRequestDto.CalculationDiscountGoods();
        calculationDiscountGoods.setGoodsId(goodsId);
        calculationDiscountGoods.setCartGoodsUid(cartGoods.getCartGoodsUid());
        calculationDiscountGoods.setAddCartTime(cartGoods.getAddCartTime() == null ? 0 : cartGoods.getAddCartTime());
        calculationDiscountGoods.setGoodsQuantity(cartGoods.getQty());
        calculationDiscountGoods.setOriginalPrice(originalPrice);
        calculationDiscountGoods.setMemberDiscount(100);
        calculationDiscountGoods.setCouponCode(couponCode);
        this.setCalculationDiscountGoods(calculationDiscountGoodsList, calculationDiscountGoods);
    }

    /**
     * 需要促销计算的商品
     *
     * @param calculationDiscountGoodsList
     * @param calculationDiscountGoods
     */
    private void setCalculationDiscountGoods(List<ActivityCalculationDiscountRequestDto.CalculationDiscountGoods> calculationDiscountGoodsList
            , ActivityCalculationDiscountRequestDto.CalculationDiscountGoods calculationDiscountGoods) {
        int index = 0;
        //当商品已经存在时，需要累加数量
        if ((index = calculationDiscountGoodsList.indexOf(calculationDiscountGoods)) >= 0) {
            ActivityCalculationDiscountRequestDto.CalculationDiscountGoods old = calculationDiscountGoodsList.get(index);
            calculationDiscountGoodsList.get(index).setGoodsQuantity(old.getGoodsQuantity() + calculationDiscountGoods.getGoodsQuantity());
        } else {
            calculationDiscountGoodsList.add(calculationDiscountGoods);
        }

    }

    /**
     * 公共DTO头
     *
     * @param partnerId
     * @param storeId
     * @param userId
     * @param appId
     * @param orderType
     * @return
     */
    private ActivityCalculationDiscountRequestDto commonSharingDto(String partnerId, String storeId, String userId, String appId, Integer orderType) {
        ActivityCalculationDiscountRequestDto calculationSharingDiscountRequestDto = new ActivityCalculationDiscountRequestDto();

        calculationSharingDiscountRequestDto.setPartnerCode(partnerId);
        calculationSharingDiscountRequestDto.setStoreId(storeId);
        calculationSharingDiscountRequestDto.setIsShowGoodsActivity(1);
        calculationSharingDiscountRequestDto.setUserId(userId);
        calculationSharingDiscountRequestDto.setAppId(appId);
        calculationSharingDiscountRequestDto.setVer(1);
        calculationSharingDiscountRequestDto.setSelectActivityList(new ArrayList<>());
        ActivityChannelEnum activityChannelEnum = PropertyConvertUtil.orderTypeConvert2ActivityChannel(orderType);
        if (!Objects.isNull(activityChannelEnum)) {
            calculationSharingDiscountRequestDto.setChannel(activityChannelEnum.getCode());
        }

        //==========================  购物车查询特有逻辑  =================================
        // 到店自取包装费设为null,外卖要计算包装费，flag为1表示去结算
        // 兼容老版本判断null
        if (Objects.equals(orderType, CreateOrderType.COLLECT_GOODS.getCode())) {
            calculationSharingDiscountRequestDto.setProductChannel(BusinessTypeEnum.SAAS_PICKUP.getCode());
        } else if (Objects.equals(orderType, CreateOrderType.TAKE_OUT.getCode())) {
            calculationSharingDiscountRequestDto.setProductChannel(BusinessTypeEnum.SAAS_DELIVERY.getCode());
        }
        return calculationSharingDiscountRequestDto;
    }
}
