/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @Title: CouponService
 * @Package cn.freemud.service
 * @Description:
 * @author: pengfei.liu
 * @date: 2020/11/23
 * @version V1.0
 * @Copyright: 2020 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */

package cn.freemud.service.delivery.impl;

import cn.freemud.entities.dto.console.*;
import cn.freemud.entities.vo.QueryDeliveryDistanceRequest;
import cn.freemud.entities.vo.QueryDeliveryDistanceResponseVo;
import cn.freemud.entities.vo.ShoppingCartGoodsResponseVo;
import cn.freemud.enums.ResponseResult;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.service.delivery.DeliveryService;
import cn.freemud.service.thirdparty.ConsoleApiClient;
import cn.freemud.service.thirdparty.DeliveryFeiginClient;
import cn.freemud.utils.LocationUtil;
import com.freemud.application.sdk.api.log.LogThreadLocal;
import com.freemud.application.sdk.api.membercenter.request.QueryReceiveAddressRequest;
import com.freemud.application.sdk.api.membercenter.response.QueryReceiveAddressResponse;
import com.freemud.application.sdk.api.membercenter.service.MemberCenterService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

@Service("gradDeliveryService")
public class GradDeliveryServiceImpl extends AbstractDeliveryServiceImpl implements DeliveryService {

    @Autowired
    private MemberCenterService memberCenterService;
    @Autowired
    private DeliveryFeiginClient deliveryFeiginClient;
    @Autowired
    private ConsoleApiClient consoleApiClient;

    @Override
    public Long calculateDeliveryAmount(String receiveId, String partnerId, String storeId, ShoppingCartGoodsResponseVo shoppingCartGoodsResponseVo) {
        String trackingNo = LogThreadLocal.getTrackingNo();
        QueryReceiveAddressRequest queryReceive = new QueryReceiveAddressRequest(receiveId, partnerId);
        //查询会员收获地址经纬度
        com.freemud.application.sdk.api.base.BaseResponse<QueryReceiveAddressResponse> queryReceiveAddressResponse = memberCenterService.queryReceiveAddressById(queryReceive, trackingNo);
        if (!ResponseResult.SUCCESS.getCode().equals(queryReceiveAddressResponse.getCode()) || queryReceiveAddressResponse.getData() == null) {
            throw new ServiceException(ResponseResult.USER_GETRECEIVEADDRESS_ERROR);
        }
        // fisherman  新配送费计算 调用门店接口
        DeliveryDto deliveryDataMsg = getDeliveryDataMsg(queryReceiveAddressResponse.getData().getLatitude(),
                queryReceiveAddressResponse.getData().getLongitude(),
                partnerId,
                storeId);
        if (null != shoppingCartGoodsResponseVo) shoppingCartGoodsResponseVo.setDeliveryFeeZeroReason(deliveryDataMsg.deliveryFeeZeroReason);
        return deliveryDataMsg.deliveryAmount;
    }

    @Override
    public Long calculateDeliveryAmount(String receiveId, String partnerId, String storeId) {
        return this.calculateDeliveryAmount(receiveId, partnerId, storeId, null);
    }


    class DeliveryDto {
        /**
         * 配送费
         */
        Long deliveryAmount;
        /**
         * 配送费为零的原因：0:正常,1:超出配送范围
         */
        Integer deliveryFeeZeroReason;
        DeliveryDto(Long amount, Integer reason) {
            deliveryAmount = amount;
            deliveryFeeZeroReason = reason;
        }
    }

    /**
     * 获取 配送费 及预计送达时间接口
     * @param userLat       用户纬度
     * @param userLong      用户经度
     * @param partnerId     商户号
     * @param storeCode     门店号
     * @return
     */
    private DeliveryDto getDeliveryDataMsg(String userLat,
                                                     String userLong,
                                                     String partnerId,
                                                     String storeCode) {
        boolean check = StringUtils.isEmpty(userLat) ||
                StringUtils.isEmpty(userLong) ||
                StringUtils.isEmpty(partnerId) ||
                StringUtils.isEmpty(storeCode);
        if (check) {
            throw new ServiceException(ResponseResult.PARAMETER_MISSING);
        }
        // 查询门店相关信息
        GetStoreMixRequest query = GetStoreMixRequest.builder()
                .partnerId(partnerId)
                .storeCode(storeCode)
                .query(QueryFlag.builder().queryStoreInfo(true).queryDeliveryInfo(true).build())
                .build();
        ConsoleResponseDTO<BizDTO> responseDto = consoleApiClient.getStoreMix(query);
        if (responseDto == null) {
            throw new ServiceException(ResponseResult.SYSTEM_BUSINESS_ERROR);
        }
        if(!ResponseResult.SUCCESS.getCode().equals(responseDto.getStatusCode()) || responseDto.getBizVO() == null){
            throw new ServiceException(ResponseResult.STORE_QUERYEXPECTARRIVETIME);
        }
        StoreInfoDTO storeInfo = responseDto.getBizVO().getStoreInfo();
        DeliveryInfoDTO deliveryInfo = responseDto.getBizVO().getDeliveryInfo();
        if (null == storeInfo || null == deliveryInfo || org.apache.commons.lang3.StringUtils.isAnyEmpty(storeInfo.getLatitude(), storeInfo.getLongitude())) {
            throw new ServiceException(ResponseResult.STORE_DELIVERY_AMOUNT_ERROR);
        }
        Long amount = calcDeliveryAmount(storeInfo, deliveryInfo, userLong, userLat);
        if (amount < 0) {
            return new DeliveryDto(0L, 1);
        } else {
            return new DeliveryDto(amount, 0);
        }
    }

    /**
     * 校验地址是否在门店配送范围内
     *
     * @param storeInfo
     * @param deliveryInfo
     * @param userLongitude
     * @param userLatitude
     * @return
     */
    private boolean isDeliveryInclude(StoreInfoDTO storeInfo, DeliveryInfoDTO deliveryInfo, String userLongitude, String userLatitude) {
        if (null == deliveryInfo) return false;

        Integer scopeConfig = deliveryInfo.getScopeConfig();
        // 配送范围绘制方式： 1-自定义 2-半径
        if ("2".equals(scopeConfig)) {
            if (deliveryInfo.getDeliveryRadius() == null || deliveryInfo.getDeliveryRadius() <= 0) {
                throw new ServiceException(ResponseResult.STORE_DELIVERY_AMOUNT_ERROR);
            }
            //用户收货地址距离门店距离 单位米
            double distance = LocationUtil.getDistance(Double.parseDouble(storeInfo.getLatitude()), Double.parseDouble(storeInfo.getLongitude()),
                    Double.parseDouble(userLatitude), Double.parseDouble(userLongitude));
            if (distance > deliveryInfo.getDeliveryRadius().doubleValue()) {
                return false;
            }
        } else if (!LocationUtil.gpsIsInclude(userLongitude, userLatitude, storeInfo.getDistributionScope())) {
            // 超出配送范围
            return true;
        }

        return true;
    }

    /**
     * 计算配送费 (超出配送范围  返回-1)
     *
     * @param storeInfo
     * @param deliveryInfo
     * @param userLongitude 用户地址经度
     * @param userLatitude  用户地址纬度
     * @return
     */
    public Long calcDeliveryAmount(StoreInfoDTO storeInfo, DeliveryInfoDTO deliveryInfo, String userLongitude, String userLatitude) {
        if (! this.isDeliveryInclude(storeInfo, deliveryInfo, userLongitude, userLatitude)) {
            //超出配送范围， 配送费设置为 -1
            return -1L;
        }

        //用户收货地址距离门店距离 单位米 如果门店没有设置阶层配送费，配送费默认=基础配送费
        if (deliveryInfo.getAddRange() == null || Integer.parseInt(deliveryInfo.getAddRange()) <= 0) {
            return deliveryInfo.getDeliveryAmount() == null ? 0L : Long.parseLong(deliveryInfo.getDeliveryAmount() + "");
        }
        if (deliveryInfo.getAddRangeAmount() == null || deliveryInfo.getAddRangeAmount() <= 0) {
            return deliveryInfo.getDeliveryAmount() == null ? 0L : Long.parseLong(deliveryInfo.getDeliveryAmount() + "");
        }

        // 查询外卖的骑行距离
        Integer riderDistance;
        try {
            QueryDeliveryDistanceRequest queryDistance = new QueryDeliveryDistanceRequest(Double.parseDouble(storeInfo.getLatitude()), Double.parseDouble(storeInfo.getLongitude()), Double.parseDouble(userLatitude), Double.parseDouble(userLongitude));
            QueryDeliveryDistanceResponseVo distanceResp = deliveryFeiginClient.queryDeliveryDistance(queryDistance);
            riderDistance = distanceResp.getData().getDistance();
            if (null == riderDistance) {
                //这里直接抛出异常，走catch流程，用直线距离代替骑行距离
                throw new Exception("经纬度信息有误");
            }
        } catch (Exception e) {
            Double lineDistance = LocationUtil.getDistance(Double.parseDouble(storeInfo.getLatitude()), Double.parseDouble(storeInfo.getLongitude()),
                    Double.parseDouble(userLatitude), Double.parseDouble(userLongitude));
            riderDistance = lineDistance.intValue();
        }

        Long defaultDeliveryRange = deliveryInfo.getDeliveryRange() == null ? 0 : Long.parseLong(deliveryInfo.getDeliveryRange());
        Long deliveryAmount = deliveryInfo.getDeliveryAmount() == null ? 0 : Long.parseLong(deliveryInfo.getDeliveryAmount() + "");
        Long addRangeCount = deliveryInfo.getAddRange() == null ? 0 : Long.parseLong(deliveryInfo.getAddRange());
        Long addRangeAmount = deliveryInfo.getAddRangeAmount() == null ? 0 : Long.parseLong(deliveryInfo.getAddRangeAmount() + "");
        if (new BigDecimal(riderDistance).compareTo(new BigDecimal(defaultDeliveryRange)) <= 0) {
            return deliveryAmount;
        } else {
            //计算实际配送费
            BigDecimal extraAmount = (new BigDecimal(riderDistance).subtract(new BigDecimal(defaultDeliveryRange)))
                    .divide(new BigDecimal(addRangeCount), 0, BigDecimal.ROUND_UP)
                    .multiply(new BigDecimal(addRangeAmount));
            BigDecimal realAmount = new BigDecimal(deliveryAmount).add(extraAmount);
            return realAmount.longValue();
        }
    }
}
