
package com.tmerclub.cloud.delivery.manager;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import com.tmerclub.cloud.api.delivery.dto.CalculateAndGetDeliverInfoDTO;
import com.tmerclub.cloud.api.delivery.dto.ChangeOrderAddrDTO;
import com.tmerclub.cloud.api.delivery.dto.DeliveryOrderDTO;
import com.tmerclub.cloud.api.delivery.vo.DeliveryCompanyExcelVO;
import com.tmerclub.cloud.api.delivery.vo.DeliveryOrderFeignVO;
import com.tmerclub.cloud.api.delivery.vo.StationVO;
import com.tmerclub.cloud.api.order.manager.ConfirmOrderManager;
import com.tmerclub.cloud.api.product.feign.SkuStockFeignClient;
import com.tmerclub.cloud.api.user.feign.UserAddrFeignClient;
import com.tmerclub.cloud.api.user.feign.UserConsigneeFeignClient;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.order.constant.DeliveryType;
import com.tmerclub.cloud.common.order.dto.DvyTypeDTO;
import com.tmerclub.cloud.common.order.dto.OrderDTO;
import com.tmerclub.cloud.common.order.vo.*;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.util.Arith;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.delivery.model.SameCity;
import com.tmerclub.cloud.delivery.service.*;
import com.tmerclub.cloud.delivery.service.*;
import com.tmerclub.cloud.delivery.vo.DeliveryCompanyVO;
import com.tmerclub.cloud.order.mapper.OrderSelfStationMapper;
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.Component;

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

/**
 * @author tmerclub
 * @date 2020/12/14
 */
@Component
public class DeliveryManager {
    private static final Logger LOGGER = LoggerFactory.getLogger(DeliveryManager.class);


    @Autowired
    private SameCityService sameCityService;
    @Autowired
    private TransportManager transportManager;
    @Autowired
    private DeliveryOrderService deliveryOrderService;
    @Autowired
    private DeliveryCompanyService deliveryCompanyService;
    @Autowired
    private StationService stationService;
    @Autowired
    private TransportService transportService;
    @Autowired
    private OrderSelfStationMapper orderSelfStationMapper;
    @DubboReference
    private UserAddrFeignClient userAddrFeignClient;
    @DubboReference
    private SkuStockFeignClient skuStockFeignClient;
    @DubboReference
    private UserConsigneeFeignClient userConsigneeFeignClient;
    @Autowired
    private ConfirmOrderManager confirmOrderManager;

    private static final long TWO = -2;


    public ServerResponseEntity<UserDeliveryInfoVO> calculateAndGetDeliverInfo(CalculateAndGetDeliverInfoDTO param) {
        UserDeliveryInfoVO userDeliveryInfo = param.getUserDeliveryInfo();
        userDeliveryInfo.setSupplierIdWithShopTransFeeMap(new HashMap<>(16));
        if (CollectionUtil.isEmpty(userDeliveryInfo.getDvyTypes())) {
            return ServerResponseEntity.success(userDeliveryInfo);
        }
        // 如果是自提的话，查询出用户使用的自提用户信息
        if (Objects.equals(userDeliveryInfo.getDvyTypes().get(0).getDvyType(), DeliveryType.STATION.value())) {
            Map<Long, ShopTransFeeVO> shopIdWithShopTransFee = new HashMap<>(16);
            Map<Long, ShopTransFeeVO> preSaleTransFeeMap = new HashMap<>(16);
            ShopTransFeeVO shopTransFeeVO = new ShopTransFeeVO();
            shopTransFeeVO.setTransfee(0L);
            shopTransFeeVO.setFreeTransfee(0L);
            shopTransFeeVO.setDeliveryTemplateId(0L);
            shopTransFeeVO.setSupplierId(0L);
            shopIdWithShopTransFee.put(userDeliveryInfo.getDvyTypes().get(0).getShopId(), shopTransFeeVO);
            userDeliveryInfo.setShopIdWithShopTransFee(shopIdWithShopTransFee);
            userDeliveryInfo.setPreSaleTransFeeMap(preSaleTransFeeMap);

            // 没有自提地址了，统一使用用户地址
//            ServerResponseEntity<UserConsigneeVO> userConsigneeResponse = userConsigneeFeignClient.getUseConsignee();
//            LOGGER.info("用户选择自提，获取用户自提信息，userConsigneeResponse:{}", userConsigneeResponse);
//            if (!userConsigneeResponse.isSuccess()) {
//                LOGGER.error("用户选择自提，获取用户自提信息失败，userConsigneeResponse:{}", userConsigneeResponse);
//                return ServerResponseEntity.transform(userConsigneeResponse);
//            }
//            userDeliveryInfo.setUserConsignee(userConsigneeResponse.getData());
//            Long userId = AuthUserContext.get().getUserId();
//            List<OrderSelfStationVO> userStationList = orderSelfStationMapper.getUserStation(userId);
//            userDeliveryInfo.setOrderSelfStation(userStationList);
            userDeliveryInfo.setTotalFreeTransfee(0L);
            return ServerResponseEntity.success(userDeliveryInfo);
        }

        //多个店铺总运费
        long actualTransfee = 0;
        //店铺可配送状态
        List<ShopCityStatusVO> shopCityStatusList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        Map<Long, Integer> dvyTypeMap = userDeliveryInfo.getDvyTypes().stream().collect(Collectors.toMap(DvyTypeDTO::getShopId, DvyTypeDTO::getDvyType));
        Map<Long, List<ShopCartItemVO>> shopCartItemsMap = param.getShopCartItems().stream().collect(Collectors.groupingBy(ShopCartItemVO::getShopId));
        //同城起送费
        Map<Long, Long> shopStartDeliveryFees = new HashMap<>(Constant.INITIAL_CAPACITY);

        actualTransfee = getActualTransfee(userDeliveryInfo, actualTransfee, shopCityStatusList, dvyTypeMap, shopCartItemsMap, shopStartDeliveryFees);
        userDeliveryInfo.setShopCityStatusVOS(shopCityStatusList);
        userDeliveryInfo.setShopStartDeliveryFees(shopStartDeliveryFees);
        actualTransfee = Math.max(actualTransfee, 0);
        userDeliveryInfo.setTotalTransfee(actualTransfee);
        return ServerResponseEntity.success(userDeliveryInfo);
    }

    private long getActualTransfee(UserDeliveryInfoVO userDeliveryInfo, long actualTransfee, List<ShopCityStatusVO> shopCityStatusList, Map<Long, Integer> dvyTypeMap, Map<Long, List<ShopCartItemVO>> shopCartItemsMap, Map<Long, Long> shopStartDeliveryFees) {
        for (Map.Entry<Long, List<ShopCartItemVO>> shopKeyCartItemEntry : shopCartItemsMap.entrySet()) {
            if (!dvyTypeMap.containsKey(shopKeyCartItemEntry.getKey())) {
                LOGGER.error("店铺id:{}没有配送方式", shopKeyCartItemEntry.getKey());
                break;
            }
            int dvyType = dvyTypeMap.get(shopKeyCartItemEntry.getKey());
            long transfee = 0L;
            ShopCityStatusVO shopCityStatusVO = new ShopCityStatusVO();
            shopCityStatusVO.setShopId(shopKeyCartItemEntry.getKey());
            shopStartDeliveryFees.put(shopKeyCartItemEntry.getKey(), 0L);
            //同城配送运费计算
            if (Objects.equals(dvyType, DeliveryType.SAME_CITY.value())) {
                // 一个店铺只获取一次同城信息，先
                SameCity sameCity = sameCityService.getSameCityByShopId(shopKeyCartItemEntry.getKey());
                LOGGER.info("同城配送运费计算，获取同城配送信息：{}", sameCity);
                if (Objects.nonNull(sameCity)) {
                    shopStartDeliveryFees.put(shopKeyCartItemEntry.getKey(), sameCity.getStartFee());
                }
                transfee = sameCityService.calculateTransFee(shopKeyCartItemEntry.getValue(), userDeliveryInfo);
                LOGGER.info("同城配送运费计算结果：{}", transfee);
            }
            //快递运费计算
            if (Objects.equals(dvyType, DeliveryType.DELIVERY.value())) {
                // 将所有订单传入处理，计算运费
                transfee = transportManager.calculateTransfee(shopKeyCartItemEntry.getValue(), userDeliveryInfo);
                LOGGER.info("快递运费计算结果：{}", transfee);

            }
            shopCityStatusVO.setShopCityStatus(transfee >= 0 ? 1 : (int) transfee);
            shopCityStatusList.add(shopCityStatusVO);
            transfee = Math.max(transfee, 0);
            actualTransfee += transfee;
        }
        return actualTransfee;
    }

    public void saveDeliveryInfo(DeliveryOrderDTO deliveryOrderDTO, Integer isPurchase, Integer unDeliveryNum) {
        deliveryOrderService.saveDeliveryInfo(deliveryOrderDTO, isPurchase, unDeliveryNum);
    }

    public List<DeliveryCompanyExcelVO> listDeliveryCompany() {
        List<DeliveryCompanyVO> list = deliveryCompanyService.list();
        return BeanUtil.mapAsList(list, DeliveryCompanyExcelVO.class);
    }

    public Double getOrderChangeAddrAmount(ChangeOrderAddrDTO param) {
        UserAddrVO userAddr = param.getUserAddrVO();
        double changeAmount;
        Long freightAmount = param.getFreightAmount();
        List<ShopCartItemVO> shopCartItems = param.getShopCartItems();
        long transFee = 0;
        UserDeliveryInfoVO userDeliveryInfoVO = new UserDeliveryInfoVO();
        userDeliveryInfoVO.setUserAddr(userAddr);
        if (Objects.equals(param.getDvyType(), DeliveryType.DELIVERY.value())) {
            // 物流配送
            transFee = transportManager.calculateTransfee(shopCartItems, userDeliveryInfoVO);
            LOGGER.info("快递配送，快递运费计算结果：{}", transFee);
        } else if (Objects.equals(param.getDvyType(), DeliveryType.SAME_CITY.value())) {
            // 同城配送
            transFee = sameCityService.calculateTransFee(shopCartItems, userDeliveryInfoVO);
            if (transFee == TWO) {
                throw new LuckException("当前店铺未开启同城配送!");
            } else if (transFee == -1) {
                throw new LuckException("超出当前设置的配送距离!");
            }
        }
        return Arith.sub(transFee, freightAmount);
    }

    public List<DeliveryOrderFeignVO> listDeliveryCountByOrderIds(List<Long> orderIds) {
        return deliveryOrderService.listDeliveryCountByOrderId(orderIds);
    }

    public StationVO getStation(Long stationId) {

        return stationService.getByStationId(stationId);
    }

    public UserDeliveryInfoVO getUserDeliveryInfoVO(List<ShopCartItemVO> shopCartItems, Long userId, OrderDTO orderParam) {
        UserDeliveryInfoVO userDeliveryInfoVO = confirmOrderManager.getUserDeliveryInfoVO(shopCartItems, userId, orderParam);
        Map<Long, TransportVO> transportMap = new HashMap<>(Constant.INITIAL_CAPACITY);

        for (Long deliveryTemplateId : userDeliveryInfoVO.getDeliveryTemplateIds()) {
            boolean transportExists = Objects.isNull(deliveryTemplateId) || deliveryTemplateId == 0 || deliveryTemplateId == -1 || transportMap.containsKey(deliveryTemplateId);
            if (transportExists) {
                continue;
            }
            TransportVO transportVO = transportService.getTransportAndAllItemsById(deliveryTemplateId);
            if (Objects.nonNull(transportVO)) {
                transportMap.put(deliveryTemplateId, transportVO);
            }
        }
        userDeliveryInfoVO.setTransportMap(transportMap);
        return userDeliveryInfoVO;
    }

    public void handleStationOrder(ShopCartOrderMergerVO shopCartOrderMerger, List<ShopCartItemVO> shopCartItems, UserDeliveryInfoVO userDeliveryInfoVO) {
        Map<Long, OrderStationSpuDTO> orderStationSpuMap = confirmOrderManager.getStationOrderStockMap(shopCartItems, userDeliveryInfoVO);
        if (MapUtil.isEmpty(orderStationSpuMap)) {
            if (Objects.nonNull(userDeliveryInfoVO.getOrderSelfStation())) {
                shopCartOrderMerger.setOrderSelfStation(userDeliveryInfoVO.getOrderSelfStation());
            }
            return;
        }
        OrderSelfStationVO orderSelfStationVO = stationService.getOrderStation(userDeliveryInfoVO, new ArrayList<>(orderStationSpuMap.values()));
        userDeliveryInfoVO.setStationId(orderSelfStationVO.getStationId());
        userDeliveryInfoVO.setOrderSelfStation(orderSelfStationVO);
        shopCartOrderMerger.setOrderSelfStation(orderSelfStationVO);
        if (Objects.nonNull(userDeliveryInfoVO.getStationId())) {
            shopCartOrderMerger.setStationId(userDeliveryInfoVO.getStationId());

        }
    }
}
