package cn.freemud.demo.adapter.service;

import cn.freemud.demo.entities.bo.CouponCode;
import cn.freemud.demo.entities.bo.GetCalCostBO;
import cn.freemud.demo.entities.bo.SendGoods;
import cn.freemud.demo.entities.bo.goods.CalCostBO;
import cn.freemud.demo.entities.bo.goods.DiscountResultBO;
import cn.freemud.demo.entities.bo.goods.ShoppingCartGoodsApportionBO;
import cn.freemud.demo.entities.bo.promotion.GetCalculationDiscountBO;
import cn.freemud.demo.entities.bo.store.GetStoreBO;
import cn.freemud.demo.service.impl.DeliveryServiceImpl;
import cn.freemud.demo.utils.CommonUtils;
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.utils.PropertyConvertUtil;
import com.freemud.application.sdk.api.log.ApiLog;
import com.freemud.sdk.api.assortment.shoppingcart.constant.CommonsConstant;
import com.freemud.sdk.api.assortment.shoppingcart.enums.BusinessTypeEnum;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static java.util.stream.Collectors.toList;

@Component
public class CalculationSharingAdapter {

    @Autowired
    private DeliveryServiceImpl deliveryService;

    public CalCostBO convert2CalCostBO(GetCalCostBO bo, Boolean isMenuPage){
        DiscountResultBO discountResultBO = bo.getDiscountResultBO();
        // 计算配送费
        CalCostBO calCostBO = new CalCostBO();
        List<CartGoods> cartGoodsList = discountResultBO.getCartGoods();
        Long deliveryAmount = deliveryService.calculateDeliveryAmount(bo.getReceiveId(), bo.getPartnerId(), bo.getShopId(),
                bo.getOrderType(), bo.getManagerService());
        ArrayList<GetCalculationDiscountBO.CalculationDiscountCoupon > coupons = new ArrayList<>();
        List<SendGoods> sendGoodsList = bo.getSendGoods();
        if (!isMenuPage){
            if (StringUtils.isNotEmpty(bo.getCouponCode())) {
                GetCalculationDiscountBO.CalculationDiscountCoupon  coupon = new GetCalculationDiscountBO.CalculationDiscountCoupon ();
                coupon.setCode(bo.getCouponCode());
                coupon.setActivityCode(bo.getActivityCode());
                GetCalculationDiscountBO.CalculationDiscountCoupon calculationDiscountCoupon = coupons.stream()
                        .filter(p -> coupon.getActivityCode().equals(p.getActivityCode()) && coupon.getCode().equals(p.getCode()))
                        .findFirst().orElse(null);
                if (calculationDiscountCoupon == null){
                    coupons.add(coupon);
                }
            }
            buildCoupons(coupons, bo.getCouponCodes());
            List<ShoppingCartInfoRequestVo.SendGoods> sendGoods = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(sendGoodsList)) {
                for (SendGoods sds : sendGoodsList) {
                    ShoppingCartInfoRequestVo.SendGoods sd = new ShoppingCartInfoRequestVo.SendGoods();
                    sd.setGoodsId(sds.getGoodsId());
                    if (StringUtils.isBlank(sds.getActivityCode())) continue;
                    sd.setQty(sds.getQty());
                    sd.setOriginalPrice(0L);
                    sd.setActivityCode(sds.getActivityCode());
                    sendGoods.add(sd);
                }
            }
        }

        // 拼促销请求的dto
        GetCalculationDiscountBO calculationSharingDiscountRequestDto = this.commonSharingDto(bo.getPartnerId(), bo.getShopId(),
                bo.getUserId(), bo.getAppId(), bo.getOrderType());

        // 校验后有效的商品券map
        List<GetCalculationDiscountBO.CalculationDiscountGoods> calculationDiscountGoodsList = new ArrayList<>();
        int cartSize = cartGoodsList.size() - 1;
        for (int i = cartSize; i >= 0; i--) {
            CartGoods cartGoods = cartGoodsList.get(i);
            if (!CommonUtils.isProductCoupon(cartGoods.getCouponCode(), cartGoods.getCartGoodsUid())) {//非商品券
                this.setCommonDiscountGoods(calculationDiscountGoodsList,cartGoods);
            }
            else {//商品券->商品券ID换取商品
                String goodsId = StringUtils.isNotBlank(cartGoods.getSkuId()) ? cartGoods.getSkuId() : cartGoods.getSpuId();
                GetCalculationDiscountBO.CalculationDiscountCoupon coupon = new GetCalculationDiscountBO.CalculationDiscountCoupon();
                coupon.setCode(CommonUtils.getCouponCode(cartGoods.getCouponCode(), cartGoods.getCartGoodsUid()));
                coupon.setActivityCode(cartGoods.getActivityCode());
                coupons.add(coupon);
                if (GoodsTypeEnum.HG_COUPON_GOODS.getGoodsType().equals(cartGoods.getGoodsType())) {
                    this.setSpqDiscountGoods(calculationDiscountGoodsList, cartGoods, goodsId, cartGoods.getCouponProductPrice(), CommonUtils.getCouponCode(cartGoods.getCouponCode(), cartGoods.getCartGoodsUid()));
                } else {
                    this.setSpqDiscountGoods(calculationDiscountGoodsList, cartGoods, goodsId, cartGoods.getCouponProductPrice(), CommonUtils.getCouponCode(cartGoods.getCouponCode(), cartGoods.getCartGoodsUid()));
                }
            }
        }
        if (!isMenuPage){
            /*加价购商品不为空*/
            if (CollectionUtils.isNotEmpty(sendGoodsList)) {
                String activityCode = "";
                List<GetCalculationDiscountBO.CalculationSendGoodsReqVO> sends = new ArrayList<>();
                List<GetCalculationDiscountBO.CalculationActivityReqVO> selectActivityLists = new ArrayList<>();
                GetCalculationDiscountBO.CalculationActivityReqVO calculationActivityReqVO = new GetCalculationDiscountBO.CalculationActivityReqVO();
                for (SendGoods send : sendGoodsList) {
                    GetCalculationDiscountBO.CalculationSendGoodsReqVO reqs = new GetCalculationDiscountBO.CalculationSendGoodsReqVO();
                    reqs.setGoodsId(send.getGoodsId());
                    reqs.setGoodsQuantity(send.getQty());
                    reqs.setOriginalPrice(Optional.ofNullable(send.getOriginalPrice()).orElse(0L).intValue());
                    reqs.setNowPrice(Optional.ofNullable(send.getOriginalPrice()).orElse(0L).intValue());
                    sends.add(reqs);
                    activityCode = send.getActivityCode();
                }
                calculationActivityReqVO.setActivityCode(activityCode);
                calculationActivityReqVO.setSendGoods(sends);
                selectActivityLists.add(calculationActivityReqVO);
                calculationSharingDiscountRequestDto.setSelectActivityList(selectActivityLists);
            }
        }

        //组装促销
        calculationSharingDiscountRequestDto.setGoods(calculationDiscountGoodsList);
        calculationSharingDiscountRequestDto.setCoupons(coupons);
        calculationSharingDiscountRequestDto.setOrgIds(bo.getManagerService().getStoreService().getOrgIds(new GetStoreBO(bo.getPartnerId(), bo.getShopId())));
        calculationSharingDiscountRequestDto.setDistributionFee(deliveryAmount);
        calculationSharingDiscountRequestDto.setIsMember(discountResultBO.getIsMember());

        //剔除商品数量为空的
        calculationDiscountGoodsList.removeIf(v->v.getGoodsQuantity().equals(0));
        if (CollectionUtils.isEmpty(calculationDiscountGoodsList)) {
            calCostBO.setGetCalculationDiscountBO(null);
        } else {
            calCostBO.setGetCalculationDiscountBO(calculationSharingDiscountRequestDto);
        }
        calCostBO.setValidCouponMap(discountResultBO.getValidCouponMap());
        calCostBO.setSpqIdToCartUuidMap(discountResultBO.getSpqIdToCartUuidMap());
        calCostBO.setCartGoods(discountResultBO.getCartGoods());
        if (!isMenuPage){
            calCostBO.setDeliveryAmount(deliveryAmount);
        }
        return calCostBO;

    }

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

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

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

        GetCalculationDiscountBO.CalculationDiscountGoods calculationDiscountGoods = new GetCalculationDiscountBO.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<GetCalculationDiscountBO.CalculationDiscountGoods.Material> materials = new ArrayList<>();
            for (CartGoods.MaterialGoods materialGoods : cartGoods.getProductMaterialList()) {
                GetCalculationDiscountBO.CalculationDiscountGoods.Material material = new GetCalculationDiscountBO.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<GetCalculationDiscountBO.CalculationDiscountGoods.GroupCombox> groupBoxes = new ArrayList<>();
            for (CartGoods.ComboxGoods boxes : cartGoods.getProductComboList()) {
                GetCalculationDiscountBO.CalculationDiscountGoods.GroupCombox combo = new GetCalculationDiscountBO.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<GetCalculationDiscountBO.CalculationDiscountGoods.Material> groups = new ArrayList<>();
            for (CartGoods.ComboxGoods group : cartGoods.getProductGroupList()) {
                GetCalculationDiscountBO.CalculationDiscountGoods.Material material = new GetCalculationDiscountBO.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);
    }
    private List<GetCalculationDiscountBO.CalculationDiscountCoupon> buildCoupons(List<GetCalculationDiscountBO.CalculationDiscountCoupon> oldCoupons, List<CouponCode> coupons){


        ApiLog.info("批量使用优惠券前，oldCoupons,coupons",oldCoupons,coupons);

        for(int i = 0 ; i < oldCoupons.size() ; i++){
            GetCalculationDiscountBO.CalculationDiscountCoupon oldCoupon = oldCoupons.get(i);
            oldCoupon.setUseIndex(i);
        }



        List<String> codes = oldCoupons.stream().map(GetCalculationDiscountBO.CalculationDiscountCoupon::getCode).collect(toList());

        if (coupons != null) {
            for(int x = 0 ; x < coupons.size() ; x++){
                CouponCode cp  = coupons.get(x);
                if(codes.contains(cp.getCouponCode())){
                    continue;
                }
                GetCalculationDiscountBO.CalculationDiscountCoupon coupon = new GetCalculationDiscountBO.CalculationDiscountCoupon();
                coupon.setCode(cp.getCouponCode());
                coupon.setActivityCode(cp.getActivityCode());
                coupon.setUseIndex(cp.getIndex() == null ? x + oldCoupons.size():  cp.getIndex() + oldCoupons.size());
                oldCoupons.add(coupon);
            }
        }

        ApiLog.info("批量使用优惠券后，oldCoupons,coupons",oldCoupons,coupons);

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

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

    }

}
