package com.izouma.dingdong.service.rider;

import com.izouma.dingdong.domain.OrderGoodsSpec;
import com.izouma.dingdong.domain.rider.DeliveryFee;
import com.izouma.dingdong.domain.merchant.Merchant;
import com.izouma.dingdong.enums.DeliveryType;
import com.izouma.dingdong.exception.BusinessException;
import com.izouma.dingdong.repo.OrderInfoRepo;
import com.izouma.dingdong.repo.rider.DeliveryFeeRepo;
import com.izouma.dingdong.repo.merchant.MerchantRepo;
import com.izouma.dingdong.utils.MapUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;

@Service
@AllArgsConstructor
public class DeliveryFeeService {

    private DeliveryFeeRepo deliveryFeeRepo;
    private OrderInfoRepo   orderInfoRepo;
    private MerchantRepo    merchantRepo;

    /**
     * 配送费用
     *
     * @param merchantId      商户ID
     * @param orderGoodsSpecs 订单商品及规格
     * @param longitude       经度
     * @param latitude        纬度
     * @return 配送费
     */
    public BigDecimal deliveryFee(Long merchantId, List<OrderGoodsSpec> orderGoodsSpecs, Double longitude, Double latitude) {

        //基础费用
        BigDecimal amount;
        //算距离
        //Address address = addressRepo.findById(orderInfo.getAddressId()).orElseThrow(new BusinessException("无地址"));
        Merchant merchant = merchantRepo.findById(merchantId).orElseThrow(new BusinessException("无商户"));
        Double distance = MapUtils.distance(longitude, latitude, merchant.getLongitude(), merchant
                .getLatitude());
        //基础距离费用的配置
        DeliveryFee baseFee = deliveryFeeRepo.findAllByType(DeliveryType.BASE_FEE).get(0);
        //基础距离的配置值
        Double baseRule = new Double(baseFee.getRule());
        //费用
        amount = new BigDecimal(baseFee.getValue());
        if (distance > baseRule) {
            //超出距离费用的配置
            DeliveryFee excessCost = deliveryFeeRepo.findAllByType(DeliveryType.EXCESS_COST).get(0);
            //超出距离规格的配置值
            Double excessRule = new Double(excessCost.getRule());
            //超出费用值
            BigDecimal excessFee = new BigDecimal(excessCost.getValue());
            //超出距离规格的几倍 向上取整
            double rule = (distance - baseRule) / excessRule;
            double ceil = Math.ceil(rule);
            //加上超出的费用
            amount = amount.add(excessFee.multiply(new BigDecimal(ceil)));
        }

        //配送系数
        //骑手的商品数量
        Double num = 0.0;
        //List<OrderGoodsSpec> orderGoodsSpecs = cart.getOrderGoodsSpecs();
        for (OrderGoodsSpec o : orderGoodsSpecs) {
            num = o.getNum() + num;
        }
        //配送系数的配置
        DeliveryFee distributionFactor = deliveryFeeRepo.findAllByType(DeliveryType.NUMBER_OF_DELIVERY).get(0);
        //配送系数的配置值
        Integer factorRule = new Integer(distributionFactor.getRule());
        //配送系数
        //商品数是配送系数的几倍 每超出几件+1 向下取整
        double factor = Math.floor(num / factorRule) + 1;

        //当前日期时间
        LocalDateTime now = LocalDateTime.now();
        //繁忙系数
        //获取繁忙时间配置
        DeliveryFee minutes = deliveryFeeRepo.findAllByType(DeliveryType.BUSY_MINUTES).get(0);
        //繁忙时间配置值
        long timeRule = Long.parseLong(minutes.getRule());
        //当前时间内商家的订单列表
        int merchantOrders = orderInfoRepo.findAllByMerchantIdAndOrderTimeAfter(merchantId, now
                .plusMinutes(timeRule)).size();
        //繁忙系数配置列表
        List<DeliveryFee> merchantCoefficient = deliveryFeeRepo.findAllByType(DeliveryType.BUSYNESS_FACTOR);
        //从大到小排序
        merchantCoefficient.sort((a, b) -> b.getValue().compareTo(a.getValue()));
        //繁忙系数
        Integer mc = 1;
        for (DeliveryFee m : merchantCoefficient) {
            if (merchantOrders > Integer.parseInt(m.getRule())) {
                mc = m.getValue();
                break;
            }
        }

        //时段系数
        //当前时间
        LocalTime nowTime = now.toLocalTime();
        //时间系数
        Integer time = 1;
        //时段系数的配置列表
        List<DeliveryFee> timeCoefficient = deliveryFeeRepo.findAllByType(DeliveryType.TIME_COEFFICIENT);
        for (DeliveryFee t : timeCoefficient) {
            //时间段
            String rule = t.getRule();
            String[] arr = rule.split("-");
            LocalTime startTime = LocalTime.parse(arr[0]);
            LocalTime endTime = LocalTime.parse(arr[1]);
            if (!nowTime.isBefore(startTime) && !nowTime.isAfter(endTime)) {
                time = t.getValue();
                break;
            }
        }

        //配送费用=基础配送费用*配送费件数系数*时段系数*繁忙系数
        return amount.multiply(new BigDecimal(factor)).multiply(new BigDecimal(mc)).multiply(new BigDecimal(time));

    }

}
