package com.yami.shop.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yami.shop.bean.app.dto.ShopCartDto;
import com.yami.shop.bean.app.dto.ShopCartItemDto;
import com.yami.shop.bean.app.param.ChangeShopCartParam;
import com.yami.shop.bean.app.param.OrderItemParam;
import com.yami.shop.bean.app.param.ShopCartParam;
import com.yami.shop.bean.enums.ProdType;
import com.yami.shop.bean.event.ShopCartEvent;
import com.yami.shop.bean.model.Basket;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.ShopDetail;
import com.yami.shop.bean.model.Sku;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.util.Arith;
import com.yami.shop.common.util.CacheManagerUtil;
import com.yami.shop.dao.BasketMapper;
import com.yami.shop.service.BasketService;
import com.yami.shop.service.ProductService;
import com.yami.shop.service.ShopDetailService;
import com.yami.shop.service.SkuService;
import com.yami.shop.service.XsbMemberSupportService;
import lombok.AllArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class BasketServiceImpl extends ServiceImpl<BasketMapper, Basket> implements BasketService {

    private final BasketMapper basketMapper;
    private final CacheManagerUtil cacheManagerUtil;
    private final ApplicationContext applicationContext;
    private final SkuService skuService;
    private final ShopDetailService shopDetailService;
    private final ProductService productService;
    private final XsbMemberSupportService xsbMemberSupportService;

    @Override
    public void deleteShopCartItemsByBasketIds(String userId, List<Long> basketIds) {
        basketMapper.deleteShopCartItemsByBasketIds(userId, basketIds);
    }

    @Override
    public void addShopCartItem(ChangeShopCartParam param, String userId) {
        Basket basket = new Basket();
        basket.setBasketCount(param.getCount());
        basket.setBasketDate(new Date());
        basket.setProdId(param.getProdId());
        basket.setShopId(param.getShopId());
        basket.setChannelId(param.getChannelId());
        basket.setUserId(userId);
        basket.setSkuId(param.getSkuId());
        basketMapper.insert(basket);
    }

    @Override
    public void updateShopCartItem(Basket basket) {
        basketMapper.updateById(basket);
    }

    @Override
    public void deleteAllShopCartItems(String userId) {
        basketMapper.deleteAllShopCartItems(userId);
    }

    @Override
    public List<ShopCartItemDto> getShopCartItems(String userId, Long channelId) {
        List<ShopCartItemDto> shopCartItemDtoList = basketMapper.getShopCartItemsByPlatform(userId, channelId);
        for (ShopCartItemDto shopCartItemDto : shopCartItemDtoList) {
            shopCartItemDto.setProductTotalAmount(Arith.mul(shopCartItemDto.getProdCount(), shopCartItemDto.getPrice()));
            shopCartItemDto.setWeight(shopCartItemDto.getWeight());
            shopCartItemDto.setWeightUnit(shopCartItemDto.getWeightUnit());
        }
        xsbMemberSupportService.enrichShopCartItems(shopCartItemDtoList, userId);
        return shopCartItemDtoList;
    }

    @Override
    public List<ShopCartItemDto> getShopCartExpiryItems(String userId) {
        return basketMapper.getShopCartExpiryItems(userId);
    }

    @Override
    public void cleanExpiryProdList(String userId) {
        basketMapper.cleanExpiryProdList(userId);
    }

    @Override
    public void updateBasketByShopCartParam(String userId, List<ShopCartParam> shopCartParams) {
        basketMapper.updateDiscountItemId(userId, shopCartParams);
    }

    @Override
    public void removeShopCartItemsCacheByUserId(String userId) {
        // no-op
    }

    @Override
    public List<String> listUserIdByProdId(Long prodId) {
        return basketMapper.listUserIdByProdId(prodId);
    }

    @Override
    public List<ShopCartDto> getShopCarts(List<ShopCartItemDto> shopCartItems, Long shopId1) {
        Map<Long, List<ShopCartItemDto>> shopCartMap = shopCartItems.stream()
                .collect(Collectors.groupingBy(ShopCartItemDto::getShopId));
        if (shopId1 != null && shopId1 > 0) {
            List<ShopCartDto> shopCartDtos = Lists.newArrayList();
            List<ShopCartItemDto> shopCartItemDtoList = shopCartMap.get(shopId1);
            if (shopCartItemDtoList != null) {
                ShopCartDto shopCart = new ShopCartDto();
                shopCart.setShopId(shopId1);
                shopCart.setShopName(shopCartItemDtoList.get(0).getShopName());
                applicationContext.publishEvent(new ShopCartEvent(shopCart, shopCartItemDtoList));
                if (Objects.equals(1L, shopId1)) {
                    shopCartDtos.add(0, shopCart);
                } else {
                    shopCartDtos.add(shopCart);
                }
            }
            return shopCartDtos;
        }

        List<ShopCartDto> shopCartDtos = Lists.newArrayList();
        for (Long shopId : shopCartMap.keySet()) {
            List<ShopCartItemDto> shopCartItemDtoList = shopCartMap.get(shopId);
            ShopCartDto shopCart = new ShopCartDto();
            shopCart.setShopId(shopId);
            shopCart.setShopName(shopCartItemDtoList.get(0).getShopName());
            applicationContext.publishEvent(new ShopCartEvent(shopCart, shopCartItemDtoList));
            if (Objects.equals(1L, shopId)) {
                shopCartDtos.add(0, shopCart);
            } else {
                shopCartDtos.add(shopCart);
            }
        }
        return shopCartDtos;
    }

    @Override
    public List<ShopCartItemDto> getShopCartItemsByOrderItems(List<Long> basketId, OrderItemParam orderItem, String userId, Long channelId) {
        if (orderItem == null && CollectionUtil.isEmpty(basketId)) {
            return Collections.emptyList();
        }
        if (CollectionUtil.isEmpty(basketId) && orderItem != null) {
            List<ShopCartItemDto> directBuyItems = Collections.singletonList(getShopCartItem(orderItem));
            xsbMemberSupportService.enrichShopCartItems(directBuyItems, userId);
            return directBuyItems;
        }

        List<ShopCartItemDto> dbShopCartItems = getShopCartItems(userId, channelId);
        return dbShopCartItems.stream()
                .filter(shopCartItemDto -> basketId.contains(shopCartItemDto.getBasketId()))
                .collect(Collectors.toList());
    }

    @Override
    public ShopCartItemDto getShopCartItem(OrderItemParam orderItem) {
        Sku sku = skuService.getSkuBySkuId(orderItem.getSkuId(), orderItem.getChannelId(), orderItem.getShopId());
        if (sku == null) {
            throw new RuntimeException("Order contains an unrecognized sku");
        }
        Product prod = productService.getProductByProdId(orderItem.getProdId());
        if (prod == null) {
            throw new RuntimeException("Order contains an unrecognized product");
        }

        ShopCartItemDto shopCartItemDto = new ShopCartItemDto();
        shopCartItemDto.setBasketId(-1L);
        shopCartItemDto.setSkuId(orderItem.getSkuId());
        shopCartItemDto.setProdCount(orderItem.getProdCount());
        shopCartItemDto.setProdId(orderItem.getProdId());
        if (Objects.equals(prod.getProdType(), ProdType.PROD_TYPE_SCORE.value())) {
            shopCartItemDto.setScorePrice(sku.getSkuScore() * orderItem.getProdCount());
        }
        shopCartItemDto.setSkuName(sku.getSkuName());
        shopCartItemDto.setWeight(sku.getWeight());
        shopCartItemDto.setWeightUnit(sku.getWeightUnit());
        shopCartItemDto.setCategoryId(prod.getCategoryId());
        shopCartItemDto.setPic(StrUtil.isBlank(sku.getPic()) ? prod.getPic() : sku.getPic());
        shopCartItemDto.setProdName(sku.getProdName());
        shopCartItemDto.setProductTotalAmount(Arith.mul(sku.getPrice(), orderItem.getProdCount()));
        shopCartItemDto.setPrice(sku.getPrice());
        shopCartItemDto.setDistributionCardNo(orderItem.getDistributionCardNo());
        shopCartItemDto.setBasketDate(new Date());
        if (orderItem.getShopId() == 0) {
            shopCartItemDto.setShopId(0L);
            shopCartItemDto.setShopName(Constant.PLATFORM_SHOP_NAME);
        } else {
            ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(orderItem.getShopId());
            shopCartItemDto.setShopId(shopDetail.getShopId());
            shopCartItemDto.setShopName(shopDetail.getShopName());
        }
        return shopCartItemDto;
    }
}
