package com.freemud.sdk.api.assortment.shoppingcart.service.impl;

import ch.qos.logback.classic.Level;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.redis.RedisCache;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.freemud.application.sdk.api.couponcenter.online.domain.*;
import com.freemud.application.sdk.api.couponcenter.online.request.ActiveBatchQueryRequest;
import com.freemud.application.sdk.api.couponcenter.online.request.CouponDetailRequest;
import com.freemud.application.sdk.api.couponcenter.online.request.PartnerRequest;
import com.freemud.application.sdk.api.couponcenter.online.response.CouponDetailResponse;
import com.freemud.application.sdk.api.couponcenter.online.service.FMActiveSdkService;
import com.freemud.application.sdk.api.couponcenter.online.service.OnlineCouponSdkService;
import com.freemud.application.sdk.api.log.ErrorLog;
import com.freemud.application.sdk.api.productcenter.constant.ResponseConstant;
import com.freemud.application.sdk.api.productcenter.domain.ProductBeanDTO;
import com.freemud.application.sdk.api.productcenter.domain.ProductInfosDTO;
import com.freemud.application.sdk.api.productcenter.request.menu.GetMenuCategoryByIdsRequest;
import com.freemud.application.sdk.api.productcenter.request.product.GetProductRequest;
import com.freemud.application.sdk.api.productcenter.response.menu.GetMenuCategoryByIdsResponse;
import com.freemud.application.sdk.api.productcenter.response.menu.GetMenuCategoryInfoResponse;
import com.freemud.application.sdk.api.productcenter.response.product.GetProductInfosResponse;
import com.freemud.application.sdk.api.productcenter.service.MenuService;
import com.freemud.application.sdk.api.productcenter.service.ProductService;
import com.freemud.sdk.api.assortment.shoppingcart.adapter.ShoppingCartAdapter;
import com.freemud.sdk.api.assortment.shoppingcart.constant.*;
import com.freemud.sdk.api.assortment.shoppingcart.domain.*;
import com.freemud.sdk.api.assortment.shoppingcart.request.CheckCartRequest;
import com.freemud.sdk.api.assortment.shoppingcart.request.GetProductInfoRequest;
import com.freemud.sdk.api.assortment.shoppingcart.service.ShoppingCartBaseService;
import com.freemud.sdk.api.assortment.shoppingcart.util.CartResponseUtil;
import com.freemud.sdk.api.assortment.shoppingcart.util.DateTimeUtils;
import com.freemud.sdk.api.assortment.shoppingcart.util.PropertyConvertUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @version V1.0
 * @Title: ShoppingCartBaseServiceImpl
 * @Package com.freemud.sdk.api.assortment.shoppingcart.service.impl
 * @Description:
 * @author: yuhao.chi
 * @date: 2019/4/10 15:30
 * @Copyright: 2019 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目的
 */
@Service("shoppingCartBaseService")
public class ShoppingCartBaseServiceImpl implements ShoppingCartBaseService {

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private MenuService menuService;
    @Autowired
    private ShoppingCartAdapter shoppingCartAdapter;
    @Autowired
    private OnlineCouponSdkService onlineCouponSdkService;
    @Autowired
    private FMActiveSdkService fmActiveSdkService;
    @Autowired
    private ProductService productService;

    @Override
    public BaseResponse<List<CartAddItem>> detailCart(CartParamDto cartParamDto, String trackingNo) {
        try {
            String mergeMerchantUserId = cartParamDto.getPartnerId() + "_" + cartParamDto.getUserId();
            String redisKey = RedisKeyConstant.SAAS_USER_INFO_CART_CARTADDPRODUCT + mergeMerchantUserId;
            List<CartAddItem> itemList = redisCache.hashGet(redisKey, cartParamDto.getStoreId());
            return CartResponseUtil.success(itemList);
        } catch (Exception e) {
            ErrorLog.printErrorLog("assortment-shoppingcart-sdk", trackingNo, e.getMessage(), "detailCart", cartParamDto, e, Level.ERROR);
            return null;
        }
    }

    @Override
    public BaseResponse<List<CartGoods>> getCartGoodsList(CartParamDto cartParamDto, String trackingNo) {
        try {
            String redisKey = getShoppingCartGoodsKey(cartParamDto);
            BoundHashOperations<String, String, CartGoods> operations = redisTemplate.boundHashOps(redisKey);
            List<CartGoods> cartGoodsList = operations.values();
            //对创建时间进行排序
            cartGoodsList.sort(Comparator.comparingLong(CartGoods::getCreateTimeMili));
            return CartResponseUtil.success(cartGoodsList);
        } catch (Exception e) {
            ErrorLog.printErrorLog("assortment-shoppingcart-sdk", trackingNo, e.getMessage(), "getCartGoodsList", cartParamDto, e, Level.ERROR);
            return null;
        }
    }

    @Override
    public BaseResponse<List<CartGoods>> setCartGoodsList(CartParamDto cartParamDto, String trackingNo) {
        try {
            String redisKey = getShoppingCartGoodsKey(cartParamDto);
            BoundHashOperations<String, String, CartGoods> operations = redisTemplate.boundHashOps(redisKey);
            this.clear(cartParamDto, trackingNo);
            Map<String, CartGoods> cartGoodsMap = cartParamDto.getCartGoodsList().parallelStream()
                    .filter(k -> StringUtils.isNotEmpty(k.getCartGoodsUid()))
                    .collect(Collectors.toMap(CartGoods::getCartGoodsUid, Function.identity(), (k1, k2) -> k1));
            operations.putAll(cartGoodsMap);
            return CartResponseUtil.success();
        } catch (Exception e) {
            ErrorLog.printErrorLog("assortment-shoppingcart-sdk", trackingNo, e.getMessage(), "setCartGoodsList", cartParamDto, e, Level.ERROR);
            return null;
        }
    }

    @Override
    public BaseResponse<CartGoods> getCartGoods(CartParamDto cartParamDto, String trackingNo) {
        try {
            String redisKey = getShoppingCartGoodsKey(cartParamDto);
            BoundHashOperations<String, String, CartGoods> operations = redisTemplate.boundHashOps(redisKey);
            CartGoods cartGoods = operations.get(cartParamDto.getCartGoodsUid());
            return CartResponseUtil.success(cartGoods);
        } catch (Exception e) {
            ErrorLog.printErrorLog("assortment-shoppingcart-sdk", trackingNo, e.getMessage(), "getCartGoods", cartParamDto, e, Level.ERROR);
            return null;
        }
    }

    @Override
    public BaseResponse<List<CartGoods>> updateGoodsQty(CartParamDto cartParamDto, String trackingNo) {
        try {
            String redisKey = getShoppingCartGoodsKey(cartParamDto);
            BoundHashOperations<String, String, CartGoods> operations = redisTemplate.boundHashOps(redisKey);
            CartGoods cartGoods = operations.get(cartParamDto.getCartGoodsUid());
            if (cartGoods != null) {
                // 当数量为0时,移除
                if (Objects.equals(cartParamDto.getQty(), 0)) {
                    operations.delete(cartParamDto.getCartGoodsUid());
                } else {
                    cartGoods.setQty(cartParamDto.getQty());
                    operations.put(cartParamDto.getCartGoodsUid(), cartGoods);
                }
            }
            return this.getCartGoodsList(cartParamDto, trackingNo);
        } catch (Exception e) {
            ErrorLog.printErrorLog("assortment-shoppingcart-sdk", trackingNo, e.getMessage(), "updateGoodsQty", cartParamDto, e, Level.ERROR);
            return null;
        }
    }

    @Override
    public BaseResponse clear(CartParamDto cartParamDto, String trackingNo) {
        try {
            redisTemplate.delete(this.getShoppingCartGoodsKey(cartParamDto));
            redisTemplate.delete(this.getShoppingCartGoodsAmountKey(cartParamDto));
            return new BaseResponse(VersionUtils.VER_1, CartResponseConstant.SUCCESS.getCode(), CartResponseConstant.SUCCESS.getMessage());
        } catch (Exception e) {
            ErrorLog.printErrorLog("assortment-shoppingcart-sdk", trackingNo, e.getMessage(), "clear", cartParamDto, e, Level.ERROR);
            return null;
        }
    }

    /**
     * 修正购物车中的spu和sku商品信息
     *
     * @param cartGoods
     * @param productBean
     * @param shoppingCartGoodsResponseVo
     * @return
     */
    private void updateSpuClassCartGoodsInfo(CartGoods cartGoods, ProductBeanDTO productBean, ShoppingCartGoodsResponseVo shoppingCartGoodsResponseVo, CartGoodsStates cartGoodsStates) {
        // 查询到的商品信息
        List<String> allAttributes = new ArrayList<>();
        List<ProductBeanDTO.ProductAttributeGroupListBean> attributeGroupListBeanList =
                productBean.getProductAttributeGroupList();
        if (CollectionUtils.isNotEmpty(attributeGroupListBeanList)) {
            for (ProductBeanDTO.ProductAttributeGroupListBean productAttributeGroupListBean : attributeGroupListBeanList) {
                List<String> attributes = productAttributeGroupListBean
                        .getAttributeValues()
                        .parallelStream()
                        .map(ProductBeanDTO.ProductAttributeGroupListBean.AttributeValueBean::getAttributeId)
                        .collect(Collectors.toList());
                allAttributes.addAll(attributes);
            }
        }
        // 购物车商品属性信息比对
        StringBuilder specProductIdBuilder = new StringBuilder();
        StringBuilder subNameBuilder = new StringBuilder();
        if (CollectionUtils.isNotEmpty(cartGoods.getExtra())) {
            for (CartGoods.CartGoodsExtra cartGoodsExtra : cartGoods.getExtra()) {
                String attributeId = cartGoodsExtra.getAttributeId();
                String attributeName = cartGoodsExtra.getAttributeName();
                if (allAttributes.contains(attributeId)) {
                    specProductIdBuilder.append(attributeId);
                    subNameBuilder.append("/");
                    subNameBuilder.append(attributeName);
                } else {
                    // 标记非法商品
                    cartGoods.setCartGoodsUid(null);
                    cartGoodsStates.setHasInvalidGoods(true);
                }
            }
        }
        cartGoods.setName(productBean.getName());
        cartGoods.setSpuName(productBean.getName());
        cartGoods.setSpecProductId(specProductIdBuilder.toString());
        cartGoods.setSubName(subNameBuilder.toString());
        cartGoods.setPic(productBean.getPicture());
        cartGoods.setPackPrice(productBean.getPackPrice());

        // 多规格商品
        if (StringUtils.isNotEmpty(cartGoods.getSkuId())) {
            if (CollectionUtils.isNotEmpty(productBean.getSkuList())) {
                List<ProductBeanDTO.SkuProductBean> skuLists = productBean.getSkuList();
                Map<String, ProductBeanDTO.SkuProductBean> skuSpecValueMap = skuLists.stream().collect(Collectors.toMap(p -> p.getSkuId(), (p) -> p));
                if (skuSpecValueMap.get(cartGoods.getSkuId()) != null) {
                    //多规格设置包装费
                    cartGoods.setPackPrice(skuSpecValueMap.get(cartGoods.getSkuId()).getPackPrice());
                    cartGoods.setOriginalPrice(skuSpecValueMap.get(cartGoods.getSkuId()).getFinalPrice());
                }
            }
        } else {
            // 单规格商品
            Long newOrigOriginalPrice = productBean.getFinalPrice();
            Long oldOrigOriginalPrice = cartGoods.getOriginalPrice();
            if (!Objects.equals(newOrigOriginalPrice, oldOrigOriginalPrice)) {
                cartGoods.setOriginalPrice(newOrigOriginalPrice);
                cartGoodsStates.setPriceChanged(true);
            }
            cartGoods.setSubName(subNameBuilder.toString().startsWith("/") ? subNameBuilder.toString().substring(1) : subNameBuilder.toString());
        }
        if (shoppingCartGoodsResponseVo != null) {
            shoppingCartGoodsResponseVo.setPackAmount(sumOf(shoppingCartGoodsResponseVo.getPackAmount(), cartGoods.getPackPrice(), cartGoods.getQty()));
        }
    }

    private Long sumOf(Long a, Long b, Integer qty) {
        a = a == null ? 0 : a;
        b = b == null ? 0 : b;
        return a + b * qty;
    }

    /**
     * 修正购物车中的sku商品信息
     *
     * @param cartGoods
     * @param productBean
     * @return
     */
//    private void updateSkuClassCartGoodsInfo(CartGoods cartGoods, ProductBeanDTO productBean, CartGoodsStates cartGoodsStates) {
//        Long newOrigOriginalPrice = productBean.getFinalPrice();
//        Long oldOrigOriginalPrice = cartGoods.getOriginalPrice();
//        if (!Objects.equals(newOrigOriginalPrice, oldOrigOriginalPrice)) {
//            cartGoods.setOriginalPrice(newOrigOriginalPrice);
//            cartGoodsStates.setPriceChanged(true);
//        }
//        cartGoods.setSkuName(productBean.getName());
//        cartGoods.setOriginalPrice(productBean.getOriginalPrice());
//        cartGoods.setPackPrice(productBean.getPackPrice());
//        // 多规格商品需要拼接skuId对应的Name
//        String specificationName = productBean.getName().replace(cartGoods.getName(), "");
//        if (specificationName.startsWith("/")) {
//            specificationName = specificationName.substring(1);
//        }
//        cartGoods.setSubName(specificationName + cartGoods.getSubName());
//    }


    /**
     * 获取记录购物车信息的key
     *
     * @return
     */
    private String getShoppingCartGoodsKey(CartParamDto cartParamDto) {
        return RedisKeyConstant.SAAS_SHOPPINGCART_KEY_PREFIX + cartParamDto.getPartnerId() + "_" + cartParamDto.getStoreId() + "_" + cartParamDto.getUserId();
    }

    /**
     * 获取记录购物车价格的key
     *
     * @return
     */
    private String getShoppingCartGoodsAmountKey(CartParamDto cartParamDto) {
        return RedisKeyConstant.SAAS_SHOPPINGCART_AMOUNT_PREFIX + cartParamDto.getPartnerId() + "_" + cartParamDto.getStoreId() + "_" + cartParamDto.getUserId();
    }
    @Value("${coupon.app.id}")
    private String appId;

    @Override
    public String getCouponAppId(){
        return this.appId;
    }

    /**
     * 批量查询活动详情
     *
     * @param partnerId
     * @param activityCodes
     * @param trackingNo
     * @return
     */
    private List<ActiveDetailVO> batchQueryActivityInfo(String partnerId, List<String> activityCodes, String trackingNo) {
        String appKey = getAppKey(partnerId, trackingNo);
        if (StringUtils.isEmpty(appKey)) {
            return null;
        }
        ActiveBatchQueryRequest activeBatchQueryRequest = new ActiveBatchQueryRequest();
        //去重
        List<String> activeCodes = new ArrayList<>(new HashSet(activityCodes));
        activeBatchQueryRequest.setActiveCode(activeCodes);
        activeBatchQueryRequest.setAppSecret(appKey);
        activeBatchQueryRequest.setPartnerId(Integer.parseInt(partnerId));
        com.freemud.application.sdk.api.base.BaseResponse<List<ActiveDetailVO>> batchQueryResponse = fmActiveSdkService.batchQueryActivityInfo(activeBatchQueryRequest, trackingNo);
        if (batchQueryResponse == null || !CartResponseConstant.SUCCESS.getCode().equals(batchQueryResponse.getCode()) || CollectionUtils.isEmpty(batchQueryResponse.getData())) {
            return null;
        }

        return batchQueryResponse.getData();
    }


    /**
     * 校验点餐方式
     * key = 活动code , value = 返回是否匹配点餐方式
     *
     * @param partnerId
     * @param activityCodes
     * @param orderTye
     * @param trackingNo
     * @return
     */
    @Override
    public Map<String, Boolean> getCouponOrderWay(String partnerId, List<String> activityCodes, Integer orderTye, String trackingNo) {
        try {
            List<ActiveDetailVO> activeDetailVOList = batchQueryActivityInfo(partnerId, activityCodes, trackingNo);
            if (CollectionUtils.isEmpty(activeDetailVOList)) {
                return null;
            }
            Map<String, Boolean> result = new HashMap<>();
            ActivityChannelEnum activityChannelEnum = PropertyConvertUtil.orderTypeConvert2ActivityChannel(orderTye);
            activeDetailVOList.forEach(active -> {
                if (Objects.isNull(active.getRedeemChannel())) {
                    result.put(active.getActiveCode(), true);
                } else {
                    result.put(active.getActiveCode(), Arrays.stream(active.getRedeemChannel().split(",")).anyMatch(Predicate.isEqual(activityChannelEnum.getCode())));
                }
            });

            return result;
        } catch (Exception e) {
            ErrorLog.printErrorLog("assortment-shoppingcart-sdk", trackingNo, e.getMessage(), "getCouponOrderWay", null, e, Level.ERROR);
            return null;
        }

    }

}
