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.CalculationSharingDiscountRequestDto;
import cn.freemud.entities.dto.calculate.CalculationSharingDiscountResponseDto;
import cn.freemud.entities.vo.CartGoods;
import cn.freemud.entities.vo.ShoppingCartInfoRequestVo;
import cn.freemud.enums.*;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.service.CommonService;
import cn.freemud.service.CouponService;
import cn.freemud.service.impl.AssortmentSdkService;
import cn.freemud.service.thirdparty.CalculationClient;
import cn.freemud.utils.PropertyConvertUtil;
import com.alibaba.fastjson.JSON;
import com.freemud.application.sdk.api.log.ErrorLog;
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 lombok.extern.slf4j.Slf4j;
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;

/**
 * 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
@Slf4j
public class CalculationSharingDiscountService {
    @Autowired
    private CouponService couponService;
    @Autowired
    private AssortmentSdkService assortmentSdkService;
    @Autowired
    private ShoppingCartBaseServiceImpl shoppingCartBaseService;
    @Autowired
    private CommonService commonService;
    @Autowired
    private CalculationClient calculationClient;

    public CalculationSharingDiscountResponseDto.CalculationDiscountResult getCalculationSharingDiscountResult(String menuType
            , String partnerId
            , String storeId
            , String userId
            , String appId
            , Integer orderType
            , boolean isMember
            , List<CartGoods> cartGoodsList
            , List<CalculationSharingDiscountRequestDto.CalculationDiscountCoupon> coupons
            , List<ShoppingCartInfoRequestVo.SendGoods> sendGoodsList
            , Long deliveryAmount) {

        CalculationSharingDiscountRequestDto calculationSharingDiscountRequestDto = this.commonSharingDto(partnerId, storeId, userId, appId, orderType);

        // 校验后有效的商品券map
        HashMap<String, CheckSpqInfoResponseDto> validCouponMap = new HashMap<>(16);
        List<CalculationSharingDiscountRequestDto.CalculationDiscountGoods> calculationDiscountGoodsList = new ArrayList<>();
        int cartSize = cartGoodsList.size() - 1;
        for (int i = cartSize; i >= 0; i--) {
            CartGoods cartGoods = cartGoodsList.get(i);
            if (!cartGoods.getCartGoodsUid().startsWith(CommonsConstant.COUPON_PREFIX)) {//非商品券
                this.setCommonDiscountGoods(calculationDiscountGoodsList,cartGoods);
            }
            else {//商品券->商品券ID换取商品
                String spqId = cartGoods.getCartGoodsUid().substring(CommonsConstant.COUPON_PREFIX.length());
                CheckSpqInfoRequestDto checkSpqInfoRequestDto = new CheckSpqInfoRequestDto(partnerId, storeId, spqId, menuType);
                CheckSpqInfoResponseDto checkSpqInfo = null;
                if (GoodsTypeEnum.HG_COUPON_GOODS.getGoodsType().equals(cartGoods.getGoodsType())) {
                    checkSpqInfo = couponService.checkSpqInfo(checkSpqInfoRequestDto, cartGoods.getSkuId());
                    log.info("coupon:{},{}", "hg", JSON.toJSONString(checkSpqInfo));
                } else {
                    checkSpqInfo = couponService.checkSpqInfo(checkSpqInfoRequestDto);
                    log.info("coupon:{},{}", "sp", JSON.toJSONString(checkSpqInfo));
                }
                if (null == checkSpqInfo) {
                    cartGoodsList.remove(i);
                    assortmentSdkService.setShoppingCart(partnerId, storeId, userId, cartGoodsList, null, null, this.shoppingCartBaseService);
                    //跑业务异常 商品券不存
                    if (GoodsTypeEnum.HG_COUPON_GOODS.getGoodsType().equals(cartGoods.getGoodsType())) {
                        throw new ServiceException(ResponseResult.SHOPPING_CART_HG_COUPON_NOT_EXIST);
                    } else {
                        throw new ServiceException(ResponseResult.SHOPPING_CART_COUPON_NOT_EXIST);
                    }
                }
                validCouponMap.put(spqId,checkSpqInfo);
                cartGoods.setName(checkSpqInfo.getCouponName());
                cartGoods.setSpuName(checkSpqInfo.getCouponName());

                CalculationSharingDiscountRequestDto.CalculationDiscountCoupon coupon = new CalculationSharingDiscountRequestDto.CalculationDiscountCoupon();
                coupon.setCode(checkSpqInfo.getCouponCode());
                coupon.setActivityCode(checkSpqInfo.getActiveCode());
                log.info("coupons={},coupon={}", JSON.toJSONString(coupons), JSON.toJSONString(coupon));
                coupons.add(coupon);

                // 添加商品券代表的商品放入促销
                String goodsId = StringUtils.isNotBlank(checkSpqInfo.getSkuId()) ? checkSpqInfo.getSkuId(): checkSpqInfo.getSpuId();

                if (GoodsTypeEnum.HG_COUPON_GOODS.getGoodsType().equals(cartGoods.getGoodsType())) {
                    this.setSpqDiscountGoods(calculationDiscountGoodsList,cartGoods,goodsId,checkSpqInfo.getPrice(),cartGoods.getSpuId());
                } else {
                    this.setSpqDiscountGoods(calculationDiscountGoodsList,cartGoods,goodsId,checkSpqInfo.getPrice());
                }
            }
        }

        /*加价购商品不为空*/
        if (CollectionUtils.isNotEmpty(sendGoodsList)) {
            String activityCode = "";
            List<CalculationSharingDiscountRequestDto.CalculationSendGoodsReqVO> sends = new ArrayList<>();
            List<CalculationSharingDiscountRequestDto.CalculationActivityReqVO> selectActivityLists = new ArrayList<>();
            CalculationSharingDiscountRequestDto.CalculationActivityReqVO calculationActivityReqVO = new CalculationSharingDiscountRequestDto.CalculationActivityReqVO();
            for (ShoppingCartInfoRequestVo.SendGoods send : sendGoodsList) {
                CalculationSharingDiscountRequestDto.CalculationSendGoodsReqVO reqs = new CalculationSharingDiscountRequestDto.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)) {
            log.info("calculationDiscountGoodsList:{}", JSON.toJSON(calculationDiscountGoodsList));
            //throw new BizServiceException(ResponseResult.SHOPPING_CART_COUPON_NOT_EXIST,"参数促销计算商品有异常");
            return null;
        }

        //组装促销
        calculationSharingDiscountRequestDto.setGoods(calculationDiscountGoodsList);
        calculationSharingDiscountRequestDto.setCoupons(coupons);
        calculationSharingDiscountRequestDto.setOrgIds(commonService.getOrgIds(partnerId,storeId));
        calculationSharingDiscountRequestDto.setDistributionFee(deliveryAmount);
        calculationSharingDiscountRequestDto.setIsMember(isMember);

        CalculationSharingDiscountResponseDto sharingDiscountResponseDto;
        try {
            log.info("start sharing discount dto={}", JSON.toJSONString(calculationSharingDiscountRequestDto));
            sharingDiscountResponseDto = calculationClient.calculationSharingDiscount(calculationSharingDiscountRequestDto);
        }
        catch (Exception e) {
            ErrorLog.printErrorLog("calculation_discount_error", "/calculation/discount/sharing", calculationSharingDiscountRequestDto, e);
            throw new ServiceException(ResponseResult.OPERATE_TOO_OFTEN);
        }

        // 返回成功
        if (sharingDiscountResponseDto != null && StringUtils.equals(sharingDiscountResponseDto.getStatusCode(), ResponseCodeConstant.RESPONSE_SUCCESS_STR)) {
            CalculationSharingDiscountResponseDto.CalculationDiscountResult result = sharingDiscountResponseDto.getResult();
            result.setValidCouponMap(validCouponMap);
            result.setDeliveryAmount(deliveryAmount);
            result.setDistributionFee(result.getDistributionFee());
            return result;
        }

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

    /**
     * 实物商品
     * @param calculationDiscountGoodsList
     * @param cartGoods
     */
    private void setCommonDiscountGoods(List<CalculationSharingDiscountRequestDto.CalculationDiscountGoods> calculationDiscountGoodsList
            , CartGoods cartGoods) {
        CalculationSharingDiscountRequestDto.CalculationDiscountGoods calculationDiscountGoods = new CalculationSharingDiscountRequestDto.CalculationDiscountGoods();
        calculationDiscountGoods.setGoodsId(cartGoods.getGoodsId());
        calculationDiscountGoods.setCartGoodsUid(cartGoods.getCartGoodsUid());
        calculationDiscountGoods.setGoodsQuantity(cartGoods.getQty());
        calculationDiscountGoods.setOriginalPrice(cartGoods.getOriginalPrice());
        calculationDiscountGoods.setMemberDiscount(cartGoods.getMemberDiscount());
        calculationDiscountGoods.setSpuId(cartGoods.getSpuId());
        //商品加料
        if (CollectionUtils.isNotEmpty(cartGoods.getProductMaterialList())) {
            ArrayList<CalculationSharingDiscountRequestDto.CalculationDiscountGoods.Material> materials = new ArrayList<>();
            for (CartGoods.MaterialGoods materialGoods : cartGoods.getProductMaterialList()) {
                CalculationSharingDiscountRequestDto.CalculationDiscountGoods.Material material = new CalculationSharingDiscountRequestDto.CalculationDiscountGoods.Material();
                material.setType(1);
                material.setGoodsId(materialGoods.getSpuId());
                material.setGoodsQuantity(1);
                material.setOriginalPrice(materialGoods.getFinalPrice());
                materials.add(material);
            }
            calculationDiscountGoods.setSmallMaterial(materials);
        }
        //商品组或是套餐或是固定搭配
        if (CollectionUtils.isNotEmpty(cartGoods.getProductComboList())) {
            ArrayList<CalculationSharingDiscountRequestDto.CalculationDiscountGoods.GroupCombox> groupBoxes = new ArrayList<>();
            for (CartGoods.ComboxGoods boxes : cartGoods.getProductComboList()) {
                CalculationSharingDiscountRequestDto.CalculationDiscountGoods.GroupCombox combo = new CalculationSharingDiscountRequestDto.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<CalculationSharingDiscountRequestDto.CalculationDiscountGoods.Material> groups = new ArrayList<>();
            for (CartGoods.ComboxGoods group : cartGoods.getProductGroupList()) {
                CalculationSharingDiscountRequestDto.CalculationDiscountGoods.Material material = new CalculationSharingDiscountRequestDto.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<CalculationSharingDiscountRequestDto.CalculationDiscountGoods> calculationDiscountGoodsList
            , CartGoods cartGoods, String goodsId, Long originalPrice) {
        CalculationSharingDiscountRequestDto.CalculationDiscountGoods calculationDiscountGoods = new CalculationSharingDiscountRequestDto.CalculationDiscountGoods();
        calculationDiscountGoods.setGoodsId(goodsId);
        calculationDiscountGoods.setCartGoodsUid(cartGoods.getCartGoodsUid());
        calculationDiscountGoods.setGoodsQuantity(1);
        calculationDiscountGoods.setOriginalPrice(originalPrice);
        calculationDiscountGoods.setMemberDiscount(100);
        this.setCalculationDiscountGoods(calculationDiscountGoodsList,calculationDiscountGoods);
    }
    private void setSpqDiscountGoods(List<CalculationSharingDiscountRequestDto.CalculationDiscountGoods> calculationDiscountGoodsList
            , CartGoods cartGoods
            , String goodsId
            , Long originalPrice
            ,String couponCode) {
        CalculationSharingDiscountRequestDto.CalculationDiscountGoods calculationDiscountGoods = new CalculationSharingDiscountRequestDto.CalculationDiscountGoods();
        calculationDiscountGoods.setGoodsId(goodsId);
        calculationDiscountGoods.setCartGoodsUid(cartGoods.getCartGoodsUid());
        calculationDiscountGoods.setGoodsQuantity(1);
        calculationDiscountGoods.setOriginalPrice(originalPrice);
        calculationDiscountGoods.setMemberDiscount(100);
        calculationDiscountGoods.setCouponCode(couponCode);
        this.setCalculationDiscountGoods(calculationDiscountGoodsList,calculationDiscountGoods);
    }

    /**
     * 需要促销计算的商品
     * @param calculationDiscountGoodsList
     * @param calculationDiscountGoods
     */
    private void setCalculationDiscountGoods(List<CalculationSharingDiscountRequestDto.CalculationDiscountGoods> calculationDiscountGoodsList
            ,CalculationSharingDiscountRequestDto.CalculationDiscountGoods calculationDiscountGoods) {
        int index = 0;
        //当商品已经存在时，需要累加数量
        if ((index = calculationDiscountGoodsList.indexOf(calculationDiscountGoods))>=0) {
            CalculationSharingDiscountRequestDto.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 CalculationSharingDiscountRequestDto commonSharingDto(String partnerId, String storeId, String userId, String appId, Integer orderType) {
        CalculationSharingDiscountRequestDto calculationSharingDiscountRequestDto = new CalculationSharingDiscountRequestDto();

        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());
        }

        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;
    }
}
