
package com.tmerclub.cloud.product.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.tmerclub.cloud.api.delivery.feign.DeliveryFeignClient;
import com.tmerclub.cloud.api.product.feign.SkuFeignClient;
import com.tmerclub.cloud.api.product.feign.SpuFeignClient;
import com.tmerclub.cloud.api.product.manager.ShopCartItemAdapter;
import com.tmerclub.cloud.api.product.util.ProductLangUtil;
import com.tmerclub.cloud.common.cache.constant.CacheNames;
import com.tmerclub.cloud.common.cache.util.CacheManagerUtil;
import com.tmerclub.cloud.common.cache.util.RedisUtil;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.i18n.I18nMessage;
import com.tmerclub.cloud.common.order.util.OrderLangUtil;
import com.tmerclub.cloud.common.order.vo.ShopCartItemVO;
import com.tmerclub.cloud.common.product.constant.SpuMold;
import com.tmerclub.cloud.common.product.constant.SpuType;
import com.tmerclub.cloud.common.product.constant.SupplierDeliveryType;
import com.tmerclub.cloud.common.product.vo.SkuVO;
import com.tmerclub.cloud.common.product.vo.SpuAndSkuVO;
import com.tmerclub.cloud.common.product.vo.SpuVO;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.product.dto.shopcart.ChangeShopCartItemDTO;
import com.tmerclub.cloud.product.dto.shopcart.CheckShopCartItemDTO;
import com.tmerclub.cloud.product.mapper.ShopCartItemMapper;
import com.tmerclub.cloud.product.model.ShopCartItem;
import com.tmerclub.cloud.product.service.ShopCartItemService;
import com.tmerclub.cloud.product.service.ShopCartService;
import com.tmerclub.cloud.product.service.SkuComboService;
import com.tmerclub.cloud.product.service.SpuService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 购物车
 *
 * @author tmerclub
 * @date 2020-11-20 15:47:32
 */
@Service
public class ShopCartServiceImpl implements ShopCartService {

    @Autowired
    private ShopCartItemMapper shopCartItemMapper;
    @Autowired
    private ShopCartItemService shopCartItemService;
    @Autowired
    private CacheManagerUtil cacheManagerUtil;
    @Autowired
    private SpuService spuService;
    @Autowired
    private SkuComboService skuComboService;
    @DubboReference
    private SpuFeignClient spuFeignClient;
    @DubboReference
    private SkuFeignClient skuFeignClient;
    @DubboReference
    private DeliveryFeignClient deliveryFeignClient;
    private final Logger LOGGER = LoggerFactory.getLogger(ShopCartItemAdapter.class);

    @Override
    @CacheEvict(cacheNames = CacheNames.SHOP_CART_ITEM_COUNT, key = "#userId")
    public void deleteShopCartItemsByShopCartItemIds(Long userId, List<Long> shopCartItemIds) {
        if (CollectionUtil.isEmpty(shopCartItemIds)) {
            return;
        }
        shopCartItemMapper.deleteShopCartItemsByShopCartItemIds(userId, shopCartItemIds);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SHOP_CART_ITEM_COUNT, key = "#userId")
    public void addShopCartItem(Long userId, ChangeShopCartItemDTO param, Long priceFee, Long categoryId) {
        ShopCartItem shopCartItem = new ShopCartItem();
        shopCartItem.setCount(param.getCount());
        shopCartItem.setSpuId(param.getSpuId());
        shopCartItem.setShopId(param.getShopId());
        shopCartItem.setUserId(userId);
        shopCartItem.setSkuId(param.getSkuId());
        shopCartItem.setCategoryId(categoryId);
        shopCartItem.setDistributionUserId(param.getDistributionUserId());
        shopCartItem.setDiscountId(0L);
        shopCartItem.setIsChecked(1);
        shopCartItem.setPriceFee(priceFee);
        shopCartItem.setComboId(param.getComboId());
        shopCartItem.setComboCount(param.getComboCount());
        shopCartItem.setParentCartItemId(param.getParentCartItemId());
        shopCartItemMapper.save(shopCartItem);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SHOP_CART_ITEM_COUNT, key = "#userId")
    public void updateShopCartItem(Long userId, ShopCartItem shopCartItem) {
        shopCartItemMapper.update(shopCartItem);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SHOP_CART_ITEM_COUNT, key = "#userId")
    public void deleteAllShopCartItems(Long userId) {
        shopCartItemMapper.deleteAllShopCartItems(userId);
    }

    @Override
    public List<ShopCartItemVO> getShopCartItems() {
        Long userId = AuthUserContext.get().getUserId();
        List<ShopCartItemVO> shopCartItems = shopCartItemMapper.getShopCartItems(userId, false, null, I18nMessage.getLang());
        for (ShopCartItemVO shopCartItem : shopCartItems) {
            shopCartItem.setTotalAmount(shopCartItem.getCount() * shopCartItem.getSkuPriceFee());
            shopCartItem.setActualTotal(shopCartItem.getTotalAmount());
            shopCartItem.setShareReduce(0L);
            OrderLangUtil.shopCartItemLang(shopCartItem);
            shopCartItem.setSpuLangList(null);
            shopCartItem.setSkuLangList(null);
            // 判断下是否为供应商商品,如果是商家代销供应商商品且为供应商发货设置供应商信息
            if (!Objects.equals(shopCartItem.getSupplierId(), 0L) && Objects.equals(shopCartItem.getSupplierDeliveryType(), 1)) {
                ServerResponseEntity<SpuAndSkuVO> spuAndSkuResponse = spuFeignClient.getSpuAndSkuAndRateById(shopCartItem.getSpuId(), shopCartItem.getSkuId(), true);
                if (!spuAndSkuResponse.isSuccess()) {
                    throw new LuckException(spuAndSkuResponse.getMsg());
                }
                SkuVO sku = spuAndSkuResponse.getData().getSku();
                SpuVO spu = spuAndSkuResponse.getData().getSpu();
                shopCartItem.setSupplierId(spu.getSupplierId());
                shopCartItem.setDeliveryTemplateId(spu.getDeliveryTemplateId());
                shopCartItem.setDeliveryAmount(spu.getDeliveryAmount());
                shopCartItem.setSupplierPriceFee(sku.getSupplyPriceFee());
                shopCartItem.setSpuName(spu.getName());
            } else {
                shopCartItem.setSupplierId(0L);
            }
            //判断用户的默认地址是否在配送范围内
            SpuVO spuVo = spuFeignClient.getById(shopCartItem.getSpuId()).getData();
            if (Objects.equals(spuVo.getSpuType(), SpuType.ACTIVE.value()) || Objects.equals(shopCartItem.getMold(), 1) || Objects.equals(userId, null)) {
                shopCartItem.setIsDelivery(true);
            } else {
                shopCartItem.setIsDelivery(deliveryFeignClient.checkAddr(shopCartItem.getDeliveryTemplateId(), userId, 0L).getData());
            }
            // 判断一下是否为组合商品,是的话处理一下
            if(Objects.equals(shopCartItem.getMold(), SpuMold.COMBO.value())){
                List<ShopCartItemVO> comboShopItems = skuComboService.getCombShopItemsAndBySkuIds(Collections.singletonList(shopCartItem.getSkuId()));
                // 放入组合的所有商品信息
                Map<Long, List<ShopCartItemVO>> skuComboMap = comboShopItems.stream().collect(Collectors.groupingBy(ShopCartItemVO::getMainComboSkuId));
                List<ShopCartItemVO> shopCartItemList = skuComboMap.get(shopCartItem.getSkuId());
                for (ShopCartItemVO shopCartItemVO : shopCartItemList) {
                    shopCartItemVO.setMainComboSpuId(shopCartItem.getSpuId());
                    shopCartItemVO.setComboCount(shopCartItem.getCount());
                }
                shopCartItemService.assembleShopCartItem(shopCartItemList, shopCartItem, null);
                shopCartItem.setComboShopCartItems(comboShopItems);
            }
        }
        // 赠品信息处理
        shopCartItemService.assembleShopCartItem(shopCartItems, null, null);
        // 组装赠品信息
        shopCartItemService.buildItemGiveawayInfo(shopCartItems);
        return shopCartItems;
    }



    @Override
    public List<ShopCartItemVO> getShopCartExpiryItems() {
        Long userId = AuthUserContext.get().getUserId();
        List<ShopCartItemVO> shopCartItems = shopCartItemMapper.getShopCartItems(userId, true, null, I18nMessage.getLang());
        List<ShopCartItemVO> itemVOList = shopCartItems.stream().filter(shopCartItemVO ->
                Objects.equals(shopCartItemVO.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())
        ).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(itemVOList)) {
            List<Long> supplierSpuIds = itemVOList.stream().map(ShopCartItemVO::getSupplierSpuId).collect(Collectors.toList());
            List<SpuVO> supplierSpuVOList = spuService.listSpuBySpuIds(supplierSpuIds);
            Map<Long, SpuVO> supplierSpuMap = supplierSpuVOList.stream().collect(Collectors.toMap(SpuVO::getSpuId, spuVO -> spuVO));
            for (ShopCartItemVO shopCartItemVO : shopCartItems) {
                if (Objects.equals(shopCartItemVO.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
                    shopCartItemVO.setSpuName(supplierSpuMap.get(shopCartItemVO.getSupplierSpuId()).getName());
                }
            }
        }

        ProductLangUtil.shopCartItemList(shopCartItems);
        for (ShopCartItemVO shopCartItem : shopCartItems) {
            shopCartItem.setTotalAmount(shopCartItem.getCount() * shopCartItem.getSkuPriceFee());
            shopCartItem.setActualTotal(shopCartItem.getTotalAmount());
        }
        return shopCartItems;
    }

    @Override
    @Cacheable(cacheNames = CacheNames.SHOP_CART_ITEM_COUNT, key = "#userId")
    public Integer getShopCartItemCount(Long userId) {
        return shopCartItemMapper.getShopCartItemCount(userId);
    }

    @Override
    public List<ShopCartItemVO> getCheckedShopCartItems() {
        Long userId = AuthUserContext.get().getUserId();
        return shopCartItemMapper.getShopCartItems(userId, false, true, I18nMessage.getLang());
    }

    @Override
    public List<ShopCartItemVO> getUserShopCartItems() {
        Long userId = AuthUserContext.get().getUserId();
        return shopCartItemMapper.getUserShopCartItems(userId);
    }

    @Override
    public void removeShopCartItemCache(List<Long> spuIds) {
        List<String> userIds = shopCartItemMapper.listUserIdBySpuIds(spuIds);
        if (CollectionUtil.isEmpty(userIds)) {
            return;
        }
        for (String userId : userIds) {
            cacheManagerUtil.evictCache(CacheNames.SHOP_CART_ITEM_COUNT, userId);
        }
    }

    @Override
    public void removeShopCartItemCacheBySupplierSpuIds(List<Long> supplierSpuIds) {
        if (CollUtil.isEmpty(supplierSpuIds)) {
            return;
        }
        List<String> userIds = shopCartItemMapper.listUserIdBySupplierSpuIds(supplierSpuIds);
        if (CollectionUtil.isEmpty(userIds)) {
            return;
        }
        for (String userId : userIds) {
            cacheManagerUtil.evictCache(CacheNames.SHOP_CART_ITEM_COUNT, userId);
        }
    }

    @Override
    public void checkShopCartItems(Long userId, List<CheckShopCartItemDTO> params) {
        shopCartItemMapper.checkShopCartItems(userId, params);
    }

    @Override
    public void updateIsClosedByShopIds(List<Long> shopIds, Integer isClosed) {
        if (shopIds == null || shopIds.size() == 0) {
            return;
        }
        shopCartItemMapper.updateIsCloseByShopIds(shopIds, isClosed);
    }

    @Override
    public void updateShopCartItemBatch(Long userId, List<ShopCartItem> shopCartItem) {
        shopCartItemMapper.updateShopCartItemBatch(shopCartItem);
    }

    @Override
    public Long getCartItemBySpuIdAndComboId(Long spuId, Long comboId, Long userId, Long skuId) {
        ShopCartItemVO cartItemBySpuIdAndComboId = shopCartItemMapper.getCartItemBySpuIdAndComboId(spuId, comboId, userId, skuId);
        if (Objects.isNull(cartItemBySpuIdAndComboId)) {
            return null;
        } else {
            return cartItemBySpuIdAndComboId.getCartItemId();
        }
    }

    @Override
    public void deleteCartByComboUpdate(List<Long> comboIdList, Long spuId, Long skuId) {
        // 清除购物车商品数量缓存
        removeShopCartItemCacheByComboId(comboIdList);
        shopCartItemMapper.deleteCartByComboUpdate(comboIdList, spuId, skuId);
    }

    public void removeShopCartItemCacheByComboId(List<Long> comboId) {
        List<String> userIds = shopCartItemMapper.listUserIdByComboIds(comboId);
        if (CollectionUtil.isEmpty(userIds)) {
            return;
        }
        for (String userId : userIds) {
            cacheManagerUtil.evictCache(CacheNames.SHOP_CART_ITEM_COUNT, userId);
        }
    }

    @Override
    public void deleteCartByComboIdAndSpuIdS(Long comboId, List<Long> spuIdList) {
        removeShopCartItemCache(spuIdList);
        shopCartItemMapper.deleteCartByComboIdAndSpuIdS(comboId, spuIdList);
    }

    @Override
    public void deleteCartByComboIdAndSkuIdS(Long comboId, List<Long> skuIdList) {
        removeShopCartItemCacheBySkuIds(skuIdList);
        shopCartItemMapper.deleteCartByComboIdAndSkuIdS(comboId, skuIdList);

    }

    public void removeShopCartItemCacheBySkuIds(List<Long> skuIds) {
        List<String> userIds = shopCartItemMapper.listUserIdBySkuIds(skuIds);
        if (CollectionUtil.isEmpty(userIds)) {
            return;
        }
        for (String userId : userIds) {
            cacheManagerUtil.evictCache(CacheNames.SHOP_CART_ITEM_COUNT, userId);
            cacheManagerUtil.evictCache(CacheNames.SHOP_CART_ITEM_COUNT, userId);
            RedisUtil.del(CacheNames.SHOP_CART_ITEM_COUNT + userId);
        }
    }


    @Override
    public void updateCartSpuPriceByComboIdAndSkuId(Long comboId, Long skuId, Long price) {
        shopCartItemMapper.updateCartSpuPriceByComboIdAndSkuId(comboId, skuId, price);
    }

    @Override
    public List<Long> skuIdListByComboMainSkuId(List<Long> skuId) {
        return shopCartItemMapper.skuIdListByComboMainSkuId(skuId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCartComboCount(Long comboId, Long spuId, Integer count) {
        List<ShopCartItemVO> shopCartItemVOList = shopCartItemMapper.listShopCartItemByComboIdAndSpuId(comboId, spuId);
        if (shopCartItemVOList.size() == 0) {
            return;
        }
        List<ShopCartItem> shopCartItemList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        ShopCartItem shopCartItem;
        for (ShopCartItemVO shopCartItemVO : shopCartItemVOList) {
            shopCartItem = new ShopCartItem();
            shopCartItem.setCartItemId(shopCartItemVO.getCartItemId());
            shopCartItem.setCount(count * shopCartItemVO.getComboCount());
            shopCartItem.setUserId(shopCartItemVO.getUserId());
            shopCartItemList.add(shopCartItem);
            // 移除用户购物车数量缓存
            cacheManagerUtil.evictCache(CacheNames.SHOP_CART_ITEM_COUNT, String.valueOf(shopCartItemVO.getUserId()));
        }
        shopCartItemMapper.updateShopCartItemBatch(shopCartItemList);

    }

}
