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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.tmerclub.cloud.api.delivery.dto.DeliveryOrderItemDTO;
import com.tmerclub.cloud.api.feign.SearchOrderFeignClient;
import com.tmerclub.cloud.api.multishop.bo.EsShopDetailBO;
import com.tmerclub.cloud.api.multishop.feign.ShopDetailFeignClient;
import com.tmerclub.cloud.api.order.bo.DistributionAmountWithOrderIdBO;
import com.tmerclub.cloud.api.order.bo.UserScoreLogOrderBO;
import com.tmerclub.cloud.api.product.feign.CategoryFeignClient;
import com.tmerclub.cloud.api.product.feign.SkuFeignClient;
import com.tmerclub.cloud.api.product.util.ProductLangUtil;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.database.util.PageUtil;
import com.tmerclub.cloud.common.database.vo.PageVO;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.i18n.I18nMessage;
import com.tmerclub.cloud.common.i18n.LanguageEnum;
import com.tmerclub.cloud.common.order.bo.EsOrderItemBO;
import com.tmerclub.cloud.common.order.constant.DeliveryType;
import com.tmerclub.cloud.common.order.constant.OrderActivityType;
import com.tmerclub.cloud.common.order.constant.OrderType;
import com.tmerclub.cloud.common.order.dto.OrderSearchDTO;
import com.tmerclub.cloud.common.order.util.OrderLangUtil;
import com.tmerclub.cloud.common.order.vo.*;
import com.tmerclub.cloud.common.product.constant.PreSaleType;
import com.tmerclub.cloud.common.product.constant.SpuMold;
import com.tmerclub.cloud.common.product.vo.CategoryVO;
import com.tmerclub.cloud.common.product.vo.SkuVO;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.common.util.LangUtil;
import com.tmerclub.cloud.common.util.PriceUtil;
import com.tmerclub.cloud.order.mapper.*;
import com.tmerclub.cloud.order.mapper.*;
import com.tmerclub.cloud.order.model.Order;
import com.tmerclub.cloud.order.model.OrderItem;
import com.tmerclub.cloud.order.model.OrderItemLang;
import com.tmerclub.cloud.order.model.OrderRefund;
import com.tmerclub.cloud.order.service.OrderItemService;
import com.tmerclub.cloud.order.vo.OrderDetailVO;
import com.tmerclub.cloud.order.vo.OrderItemDetailVO;
import com.tmerclub.cloud.order.vo.OrderRefundVO;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单项
 *
 * @author tmerclub
 * @date 2020-12-04 11:27:35
 */
@Service
public class OrderItemServiceImpl implements OrderItemService {

    private final Logger LOGGER = LoggerFactory.getLogger(OrderItemService.class);

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private OrderItemLangMapper orderItemLangMapper;

    @DubboReference
    private CategoryFeignClient categoryFeignClient;

    @DubboReference
    private ShopDetailFeignClient shopDetailFeignClient;
    @Autowired
    private OrderRefundMapper orderRefundMapper;

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderPreSaleInfoMapper orderPreSaleInfoMapper;
    @DubboReference
    private SkuFeignClient skuFeignClient;

    @DubboReference
    private SearchOrderFeignClient searchOrderFeignClient;


    @Override
    public PageVO<com.tmerclub.cloud.common.order.vo.OrderItemVO> page(PageDTO pageDTO) {
        return PageUtil.doPage(pageDTO, () -> orderItemMapper.list());
    }

    @Override
    public com.tmerclub.cloud.common.order.vo.OrderItemVO getByOrderItemId(Long orderItemId) {
        return orderItemMapper.getByOrderItemId(orderItemId, I18nMessage.getLang());
    }

    @Override
    public void save(OrderItem orderItem) {
        orderItemMapper.save(orderItem);
    }

    @Override
    public void update(OrderItem orderItem) {
        orderItemMapper.update(orderItem);
    }

    @Override
    public void deleteById(Long orderItemId) {
        orderItemMapper.deleteById(orderItemId);
    }

    @Override
    public void deleteBatchByIds(List<Long> orderItemIds) {
        orderItemMapper.deleteBatchByIds(orderItemIds);
    }

    @Override
    public List<OrderItem> listOrderItemsByOrderId(Long orderId) {
        return orderItemMapper.listOrderItemsByOrderId(orderId);
    }

    @Override
    public List<OrderItem> listOrderItemsByOrderIds(Long orderId) {
        return orderItemMapper.listOrderItemsByOrderIds(orderId);
    }

    @Override
    public List<OrderItemVO> listOrderItemAndLangByOrderId(Long orderId) {
        List<OrderItemVO> orderItems = orderItemMapper.listOrderItemAndLangByOrderIds(Collections.singletonList(orderId));
        OrderLangUtil.orderItemVOList(orderItems);
        return orderItems;
    }

    @Override
    public List<OrderItemVO> listOrderItemAndLangByOrderIds(List<Long> orderIds) {
        if (CollUtil.isEmpty(orderIds)) {
            return Collections.emptyList();
        }
        List<OrderItemVO> orderItems = orderItemMapper.listOrderItemAndLangByOrderIds(orderIds);
        OrderLangUtil.orderItemVOList(orderItems);
        return orderItems;
    }

    @Override
    public List<DistributionAmountWithOrderIdBO> sumTotalDistributionAmountByOrderIds(List<Long> orderIds) {
        return orderItemMapper.sumTotalDistributionAmountByOrderIds(orderIds);
    }

    @Override
    public void saveBatch(List<OrderItem> orderItems) {
        if (CollUtil.isEmpty(orderItems)) {
            return;
        }
        orderItemMapper.saveBatch(orderItems);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBatch(List<OrderItem> orderItems) {
        for (OrderItem orderItem : orderItems) {
            orderItemMapper.update(orderItem);
        }
    }

    @Override
    public List<String> getSpuNameListByOrderIds(long[] orderIdList) {
        List<String> spuNameList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        List<OrderItemLangVO> orderItemLangList = orderItemLangMapper.getLangListByOrderIds(orderIdList);
        Map<Long, List<OrderItemLangVO>> orderItemLangMap = orderItemLangList.stream().collect(Collectors.groupingBy(OrderItemLangVO::getOrderItemId));
        for (Long orderItemId : orderItemLangMap.keySet()) {
            Map<Integer, String> spuNameMap = orderItemLangMap.get(orderItemId).stream().collect(Collectors.toMap(OrderItemLangVO::getLang, OrderItemLangVO::getSpuName));
            spuNameList.add(LangUtil.getLangValue(spuNameMap));
        }
        return spuNameList;
    }

    @Override
    public Integer countByOrderId(Long orderId) {
        return orderItemMapper.countByOrderId(orderId);
    }

    @Override
    public Integer sumNumByOrderId(Long orderId) {
        return orderItemMapper.sumNumByOrderId(orderId);
    }

    @Override
    public void updateByDeliveries(List<DeliveryOrderItemDTO> deliveryOrderItems, Integer deliveryType, Long orderId) {
        Integer initDeliveryType = deliveryType;
        int devType;
        for (DeliveryOrderItemDTO deliveryOrderItem : deliveryOrderItems) {
            devType = orderItemMapper.getDevTypeByOrderItemId(deliveryOrderItem.getOrderItemId());
            LOGGER.info("物流配送方式为:" + devType + "传参为：" + deliveryType);
            if (Objects.equals(devType, DeliveryType.DELIVERY.value()) || Objects.equals(devType, DeliveryType.ONLINE.value())) {
                // 如果快递项已有快递类型，则set进去应当是快递类型
                deliveryType = devType;
            }
            if (Objects.equals(devType, DeliveryType.ONLINE.value()) && Objects.equals(initDeliveryType, DeliveryType.DELIVERY.value())) {
                // 如果是线上发货，现改为线下的话就更新为线下
                deliveryType = DeliveryType.DELIVERY.value();
            }
            orderItemMapper.updateByDelivery(deliveryOrderItem, deliveryType);
        }
        // 处理一下组合商品的发货
        List<OrderItem> orderItems = listOrderItemsByOrderId(orderId);
        if(orderItems.stream().filter(orderItem -> Objects.equals(orderItem.getSpuMold(), SpuMold.COMBO.value())).count() < 1){
            return;
        }
        Map<Long, List<OrderItem>> childComboItems = orderItems.stream().filter(orderItem -> Objects.equals(orderItem.getActivityType(), OrderActivityType.COMBO_PROD.value()) && !Objects.equals(orderItem.getBeDeliveredNum(),-1L))
                .collect(Collectors.groupingBy(OrderItem::getActivityId));
        List<OrderItem> updateOrderItems = new ArrayList<>();
        for (Long mainItemId : childComboItems.keySet()) {
            // 检查下是否所有的子组合项都发货了
            boolean isDelivery = true;
            List<OrderItem> items = childComboItems.get(mainItemId);
            long unDeliveryCount = items.stream().filter(orderItem -> !Objects.equals(orderItem.getBeDeliveredNum(), 0)).count();
            if(unDeliveryCount == 0){
                long count = items.stream().filter(orderItem -> Objects.equals(orderItem.getDeliveryType(), DeliveryType.DELIVERY.value())).count();
                OrderItem orderItem = new OrderItem();
                orderItem.setOrderItemId(mainItemId);
                orderItem.setBeDeliveredNum(0);
                // 如果有一个快递发货的方式,那就是快递发货,否则就是第一个的发货方式,因为如果是自提/同城配送/无需快递那就都是这三
                orderItem.setDeliveryType(count > 0 ? DeliveryType.DELIVERY.value() : items.get(0).getDeliveryType());
                orderItemMapper.update(orderItem);
            }
        }

    }

    @Override
    public int countUnDeliveryNumByOrderId(Long orderId) {
        return orderItemMapper.countUnDeliveryNumByOrderId(orderId);
    }

    @Override
    public void reduceUnDeliveryNumByOrderItemId(Long orderItemId, Integer count) {
        orderItemMapper.reduceUnDeliveryNumByOrderItemId(orderItemId, count);
    }

    @Override
    public void updateRefundStatusByOrderId(Long orderId, Integer refundStatus) {
        orderItemMapper.updateRefundStatusByOrderId(orderId, refundStatus);
    }

    @Override
    public OrderDetailVO listDetailByParam(Long orderId, Long refundId) {
        OrderDetailVO orderDetailVO = new OrderDetailVO();
        Integer lang = I18nMessage.getLang();
        List<OrderItemDetailVO> list = orderItemMapper.listDetailByOrderId(orderId, lang);
        Order order = orderMapper.getByOrderId(orderId);
        OrderPreSaleInfoVO orderPreSaleInfoVO = orderPreSaleInfoMapper.getByOrderId(orderId);
        List<OrderItem> orderItems = orderItemMapper.listOrderItemsByOrderId(orderId);
        HashSet<Long> spuIdSet = new HashSet<>(Constant.INITIAL_CAPACITY);
        orderItems.forEach(s -> spuIdSet.add(s.getSpuId()));
        List<Long> spuIds = new ArrayList<>(spuIdSet);
        List<SkuVO> skuVOList = skuFeignClient.listBySpuIds(spuIds);
        List<Long> supplierSkuIdList = skuVOList.stream()
                .filter(sku -> sku.getSupplierSkuId() != null && sku.getSupplierSkuId() != 0)
                .map(SkuVO::getSupplierSkuId).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(supplierSkuIdList)) {
            LOGGER.info("获取代销商品对应的供应商商品的sku信息，supplierSkuIdList:{}", supplierSkuIdList);
            List<SkuVO> supplierSkuVOList = skuFeignClient.getByIds(supplierSkuIdList).getData();
            Map<Long, Long> supplierSkuMap = supplierSkuVOList.stream().collect(Collectors.toMap(SkuVO::getSkuId, SkuVO::getPriceFee));
            Map<Long, Long> skuMap = skuVOList.stream()
                    .filter(sku -> sku.getSupplierSkuId() != null && sku.getSupplierSkuId() != 0)
                    .collect(Collectors.toMap(SkuVO::getSkuId, SkuVO::getSupplierSkuId));
            Map<Long, Long> itemIdMap = orderItems.stream().collect(Collectors.toMap(OrderItem::getOrderItemId, OrderItem::getSkuId));
            for (OrderItemDetailVO detailVO : list) {
                Long skuId = itemIdMap.get(detailVO.getOrderItemId());
                if (skuMap.containsKey(skuId)) {
                    detailVO.setSupplyPriceFee(supplierSkuMap.get(skuMap.get(skuId)) * detailVO.getCount());
                }
            }
        }
        // 过滤掉组合的子商品项
        list = list.stream().filter(orderItemDetailVO -> !Objects.equals(orderItemDetailVO.getActivityType(),OrderActivityType.COMBO_PROD.value())).toList();

        handleOrderData(refundId, list, order, orderPreSaleInfoVO);

        ServerResponseEntity<EsShopDetailBO> shopDetailResponseEntity = shopDetailFeignClient.getShopByShopId(order.getShopId());
        LOGGER.info("获取店铺信息，shopDetailResponseEntity:{}", shopDetailResponseEntity);
        if (!shopDetailResponseEntity.isSuccess()) {
            throw new LuckException(shopDetailResponseEntity.getMsg());
        }
        EsShopDetailBO shopDetailBO = shopDetailResponseEntity.getData();
        if (Objects.nonNull(shopDetailBO)) {
            orderDetailVO.setShopName(shopDetailBO.getShopName());
        }

        orderDetailVO.setOrderItemDetailList(list);
        orderDetailVO.setFreeFreightAmount(order.getFreeFreightAmount());
        orderDetailVO.setPlatformFreeFreightAmount(order.getPlatformFreeFreightAmount());
        orderDetailVO.setFreightAmount(order.getFreightAmount());
        return orderDetailVO;
    }

    private void handleOrderData(Long refundId, List<OrderItemDetailVO> list, Order order, OrderPreSaleInfoVO orderPreSaleInfoVO) {
        List<OrderRefund> orderRefunds = new ArrayList<>();
        if (Objects.nonNull(refundId)) {
            OrderRefundVO orderRefundVO = orderRefundMapper.getByRefundId(refundId);
            LOGGER.info("获取退款单信息，orderRefundVO:{}", orderRefundVO);
            orderRefunds.add(BeanUtil.map(orderRefundVO,OrderRefund.class));
        }else{
            orderRefunds = orderRefundMapper.listSuccessOrderRefundByOrderId(order.getOrderId());
        }
        Map<Long, OrderRefund> orderRefundMap = orderRefunds.stream().collect(Collectors.toMap(OrderRefund::getOrderItemId, orderRefund -> orderRefund));
        OrderRefund orderRefund = null;
        if(orderRefundMap.containsKey(0L)) {
            orderRefund = orderRefundMap.get(0L);
        }
        for (OrderItemDetailVO detailVO : list) {
            if (Objects.equals(order.getOrderType(), OrderType.SECKILL.value())) {
                detailVO.setSeckillAmount(detailVO.getMultishopReduce());
            } else if (Objects.equals(order.getOrderType(), OrderType.GROUP.value())) {
                detailVO.setGroupAmount(detailVO.getMultishopReduce());
            }
            if (Objects.equals(order.getPreSaleType(), PreSaleType.DEPOSIT.value()) && Objects.equals(orderPreSaleInfoVO.getPayStatus(),1)) {
                // 平台佣金
                long platformCommission = PriceUtil.divideByBankerRounding((long) (orderPreSaleInfoVO.getDepositAmount() * detailVO.getRate()), 100);
                detailVO.setActualTotal(orderPreSaleInfoVO.getDepositAmount());
                detailVO.setPlatformCommission(platformCommission);
            }
            CategoryVO categoryVO = categoryFeignClient.getByCategoryId(detailVO.getCategoryId()).getData();
            LOGGER.info("获取商品分类信息，categoryVO:{}", categoryVO);
            if (Objects.nonNull(categoryVO)) {
                ProductLangUtil.category(categoryVO);
                detailVO.setCategoryName(categoryVO.getName());
            }
            if (Objects.nonNull(orderRefund)) {
                detailVO.setRefundCount(detailVO.getCount());
                detailVO.setRefundAmount(detailVO.getActualTotal());
            } else if (orderRefundMap.containsKey(detailVO.getOrderItemId())) {
                OrderRefund orderRefundVO = orderRefundMap.get(detailVO.getOrderItemId());
                detailVO.setRefundCount(orderRefundVO.getRefundCount());
                detailVO.setRefundAmount(orderRefundVO.getRefundAmount());
                if (Objects.equals(detailVO.getActivityType(), OrderActivityType.GIVEAWAY.value())) {
                    detailVO.setRefundCount(detailVO.getCount());
                }
            }
        }
    }

    @Override
    public com.tmerclub.cloud.common.order.vo.OrderItemVO getSpuInfoByOrderItemId(Long orderItemId) {
        return orderItemMapper.getSpuInfoByOrderItemId(orderItemId, I18nMessage.getLang());
    }

    @Override
    public boolean getDevTypeByOrderId(Long orderId) {
        List<Integer> devTypes = orderItemMapper.getDevTypeByOrderId(orderId);
        return devTypes.contains(DeliveryType.DELIVERY.value()) || devTypes.contains(DeliveryType.ONLINE.value());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBatchDistributionAmount(List<EsOrderItemBO> message) {
        if (CollUtil.isEmpty(message)) {
            return;
        }
        int row = 0;
        for (EsOrderItemBO esOrderItemBO : message) {
            row += orderItemMapper.updateBatchDistributionAmount(esOrderItemBO);
        }
        if (row <= 0) {
            return;
        }
        // 将订单项里面的分销金额统计起来，加到订单的分销总金额里面
        List<Long> orderItemIds = message.stream().map(EsOrderItemBO::getOrderItemId).collect(Collectors.toList());
        OrderSearchDTO orderSearchDTO = new OrderSearchDTO();
        orderSearchDTO.setOrderItemIds(orderItemIds);
        orderSearchDTO.setPageSize(orderItemIds.size());
        orderSearchDTO.setPageNum(1);
        ServerResponseEntity<List<EsOrderVO>> orderResponseEntity = searchOrderFeignClient.listOrder(orderSearchDTO);
        List<Order> updateOrders = new ArrayList<>(Constant.INITIAL_CAPACITY);
        Map<Long, Long> amountMap = message.stream().collect(Collectors.toMap(EsOrderItemBO::getOrderItemId, EsOrderItemBO::getDistributionAmount));
        Map<Long, Long> parentAmountMap = message.stream().collect(Collectors.toMap(EsOrderItemBO::getOrderItemId, EsOrderItemBO::getDistributionParentAmount));
        for (EsOrderVO esOrderBO : orderResponseEntity.getData()) {
            List<EsOrderItemVO> items = esOrderBO.getOrderItems();
            Order update = new Order();
            update.setOrderId(esOrderBO.getOrderId());
            BigDecimal distributionAmount = new BigDecimal(BigInteger.ZERO.toString());
            for (EsOrderItemVO item : items) {
                if (amountMap.containsKey(item.getOrderItemId())) {
                    // 直推分销金额
                    distributionAmount = distributionAmount.add(new BigDecimal(amountMap.get(item.getOrderItemId()).toString()));
                    // 间推分销金额
                    if (Objects.nonNull(parentAmountMap.get(item.getOrderItemId())) && parentAmountMap.get(item.getOrderItemId()) >= 0) {
                        distributionAmount = distributionAmount.add(new BigDecimal(parentAmountMap.get(item.getOrderItemId()).toString()));
                    }
                }
            }
            update.setDistributionAmount(distributionAmount.longValue());
            updateOrders.add(update);
        }
        // 修改订单分销金额
        for (Order updateOrder : updateOrders) {
            orderMapper.updateDistributionAmount(updateOrder);
        }
    }

    @Override
    public List<UserScoreLogOrderBO> getUserScoreLogDetail(List<Long> orderIds) {
        if (CollUtil.isEmpty(orderIds)) {
            return new ArrayList<>(0);
        }
        return orderItemMapper.getUserScoreLogDetail(orderIds);
    }

    @Override
    public List<com.tmerclub.cloud.common.order.vo.OrderItemVO> getOrderItemByGiveawayOrderItemId(Long userId, Long giveawayOrderItemId) {
        if (Objects.isNull(userId) || Objects.equals(giveawayOrderItemId, 0L)) {
            return new ArrayList<>(0);
        }
        List<com.tmerclub.cloud.common.order.vo.OrderItemVO> orderItems = orderItemMapper.getOrderItemByGiveawayOrderItemId(userId, giveawayOrderItemId);
        OrderLangUtil.orderItemVOList(orderItems);
        return orderItems;
    }

    @Override
    public List<com.tmerclub.cloud.common.order.vo.OrderItemVO> getOrderItemByGiveawayOrderItemIds(List<Long> giveawayOrderItemIds, Long userId, Integer sysType) {
        List<com.tmerclub.cloud.common.order.vo.OrderItemVO> orderItems = orderItemMapper.getOrderItemByGiveawayOrderItemIds(giveawayOrderItemIds, userId, sysType);
        OrderLangUtil.orderItemVOList(orderItems);
        return orderItems;
    }

    @Override
    public List<com.tmerclub.cloud.common.order.vo.OrderItemVO> listOrderItemsByUserIdAndOrderIds(Long userId, List<Long> orderIds) {
        if (Objects.isNull(userId) || CollUtil.isEmpty(orderIds)) {
            return new ArrayList<>(0);
        }
        List<com.tmerclub.cloud.common.order.vo.OrderItemVO> orderItemList = orderItemMapper.listOrderItemsByUserIdAndOrderIds(userId, orderIds);
        OrderLangUtil.orderItemVOList(orderItemList);
        return orderItemList;
    }

    @Override
    public List<OrderItem> listByIds(List<Long> itemIds) {
        return orderItemMapper.listByIds(itemIds);
    }

    @Override
    public List<OrderItemVO> listOrderItemAndLangByOrderItemIds(List<Long> orderItemIds) {
        List<OrderItemVO> orderItemList = orderItemMapper.listOrderItemAndLangByOrderItemIds(orderItemIds);
        OrderLangUtil.orderItemVOList(orderItemList);
        return orderItemList;
    }

    @Override
    public void updateByGroupSplit(List<OrderItemVO> insertOrderItems) {
        List<Long> removeItemIds = insertOrderItems.stream().map(OrderItemVO::getOldOderItemId).toList();
        // 1.订单项处理,先删除后保存
        deleteBatchByIds(removeItemIds);
        saveBatch(BeanUtil.mapAsList(insertOrderItems,OrderItem.class));
        Map<Long, Long> oldItemMap = insertOrderItems.stream().collect(Collectors.toMap(OrderItemVO::getOldOderItemId, OrderItemVO::getOrderItemId));
        // 2.订单语言项处理,先删除之后保存
        List<OrderItemLangVO> orderItemLangList = orderItemLangMapper.listOrderItemLangByIds(removeItemIds, LanguageEnum.LANGUAGE_ZH_CN.ordinal());
        orderItemLangMapper.deleteBatchByIds(removeItemIds);
        for (OrderItemLangVO orderItemLangVO : orderItemLangList) {
            orderItemLangVO.setOrderItemId(oldItemMap.get(orderItemLangVO.getOrderItemId()));
        }
        orderItemLangMapper.saveBatch(BeanUtil.mapAsList(orderItemLangList, OrderItemLang.class));
    }
}
