package cn.freemud.management.service;

import cn.freemud.base.entity.BaseResponse;
import cn.freemud.base.log.LogTreadLocal;
import cn.freemud.management.util.CheckException;
import cn.freemud.management.util.CommonResp;
import com.freemud.application.sdk.api.deliverycenter.dto.CreateDeliveryOrderRequestDto;
import com.freemud.application.sdk.api.deliverycenter.response.CreateDeliveryOrderResponseDto;
import com.freemud.application.sdk.api.deliverycenter.service.DeliveryService;
import com.freemud.application.sdk.api.storecenter.request.StoreInfoRequest;
import com.freemud.application.sdk.api.storecenter.response.StoreResponse;
import com.freemud.application.sdk.api.storecenter.service.StoreCenterService;
import com.freemud.sdk.api.assortment.order.enums.OrderSourceType;
import com.freemud.sdk.api.assortment.order.response.order.QueryOrdersResponse;
import com.google.common.base.Throwables;
import javafx.util.Pair;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class OrderDeliveryService {

    @Autowired
    private StoreCenterService storeCenterService;
    @Autowired
    private DeliveryService deliveryService;
    @Autowired
    private OrderBaseService orderBaseService;

    @Value("${saas.order.delivery.callBackUrl}")
    private String deliveryCallBackUrl;

    private int SUCCESS = 100;
    private String delivery_type_self = "self";

    /**
     * 外卖单创建配送信息
     *
     * @param orderCode
     * @return
     */
    public BaseResponse createDelivery(String orderCode, String operator) {
        QueryOrdersResponse.DataBean.OrderBean orderBean = orderBaseService.getByOrderCode(orderCode);
        if (null == orderBean) {
            return CommonResp.fail("订单不存在");
        }
        Pair<Boolean, String> pair = checkOrderOfDelivery(orderBean);
        if (!pair.getKey()) {
            log.info("无需创建配送单({}),{}", orderBean.getOid(), pair.getValue());
            return CommonResp.success(pair.getValue());
        }
        try {
            this.createDelivery(orderBean, operator);
        } catch (CheckException e) {
            log.error("创建配送单失败({}),trace:{}", orderCode, Throwables.getStackTraceAsString(e));
            return CommonResp.fail(e.getMessage());
        }
        return CommonResp.success();
    }

    /**
     * 创建配送信息
     *
     * @param orderBean
     * @return
     */
    public Boolean createDelivery(QueryOrdersResponse.DataBean.OrderBean orderBean, String operator) {
        StoreInfoRequest storeInfoRequestDto = new StoreInfoRequest(orderBean.getCompanyId(), orderBean.getShopId());
        StoreResponse storeInfo = storeCenterService.getStoreInfo(storeInfoRequestDto, LogTreadLocal.getTrackingNo());
        if (SUCCESS != storeInfo.getStatusCode() || storeInfo.getBizVO() == null) {
            throw new CheckException("查询门店信息失败");
        }

        // 调用配送系统创建配送单
        CreateDeliveryOrderRequestDto requestDto = buildDeliveryOrderRequestDto(orderBean, storeInfo, deliveryCallBackUrl);
        CreateDeliveryOrderResponseDto deliveryResponse = deliveryService.deliveryOrderAdd(requestDto, LogTreadLocal.getTrackingNo());

        if (StringUtils.isBlank(operator)) {
            operator = "系统";
        }
        //创建配送单失败，更新订单为异常单
        if (deliveryResponse == null || SUCCESS != deliveryResponse.getCode() || deliveryResponse.getData() == null) {
            String deliveryId = deliveryResponse != null && deliveryResponse.getData() != null ? deliveryResponse.getData().getDeliveryId() : "";
            orderBaseService.updateDeliveryAbnormal(orderBean.getCompanyId(), orderBean.getOid(), deliveryId, operator);
            throw new CheckException("创建配送单信息失败，配送状态更新为配送异常");
        }
        // 创建配送单成功
        orderBaseService.updateDeliverySuccess(orderBean.getOid(), deliveryResponse.getData().getDeliveryId(), operator);
        return true;
    }

    /**
     * 校验订单是否符合创建配送单要求
     *
     * @param orderBean
     * @return
     */
    public Pair<Boolean, String> checkOrderOfDelivery(QueryOrdersResponse.DataBean.OrderBean orderBean) {
        //判断外卖单
        if (1 != orderBean.getType()) {
            return new Pair<>(false, "该订单不是外卖类型订单");
        }
        if (!orderBean.getSource().equalsIgnoreCase(OrderSourceType.SAAS.getCode())) {
            return new Pair<>(false, "订单来源异常");
        }
        //配送信息为空，则不创建配送单
        if (orderBean.getAddInfo() == null || orderBean.getAddInfo().getDeliveryType() == null) {
            return new Pair<>(false, "未找到订单配送信息");
        }
        //自配送不创建配送单
        if (delivery_type_self.equalsIgnoreCase(orderBean.getAddInfo().getDeliveryType())) {
            return new Pair<>(false, "该订单为自配送");
        }
        return new Pair<>(true, "success");
    }

    /**
     * 创建配送单请求对象
     *
     * @param order
     * @param storeInfo
     * @param deliveryCallBackUrl
     * @return
     */
    private CreateDeliveryOrderRequestDto buildDeliveryOrderRequestDto(QueryOrdersResponse.DataBean.OrderBean order
            , StoreResponse storeInfo, String deliveryCallBackUrl) {

        CreateDeliveryOrderRequestDto deliveryOrderRequestDto = new CreateDeliveryOrderRequestDto();
        deliveryOrderRequestDto.setDepatchWeight(new BigDecimal(1));
        deliveryOrderRequestDto.setSerialNumber(order.getDaySeq().toString());
        deliveryOrderRequestDto.setOrderId(order.getOid());
        deliveryOrderRequestDto.setOrderRemark(order.getRemark());
        deliveryOrderRequestDto.setOrderTotalAmount(order.getAmount().intValue());
        deliveryOrderRequestDto.setOrderActualAmount(order.getAmount().intValue());
        deliveryOrderRequestDto.setPartnerId(order.getCompanyId());
        deliveryOrderRequestDto.setOrderChannel(order.getSource());
        deliveryOrderRequestDto.setStoreId(storeInfo.getBizVO().getStoreId());
        deliveryOrderRequestDto.setStoreCode(storeInfo.getBizVO().getStoreCode());
        StringBuffer address = new StringBuffer(storeInfo.getBizVO().getCity())
                .append(storeInfo.getBizVO().getProvince())
                .append(storeInfo.getBizVO().getRegion())
                .append(storeInfo.getBizVO().getAddress());
        deliveryOrderRequestDto.setStoreAddress(address.toString());
        deliveryOrderRequestDto.setStoreLng(new BigDecimal(storeInfo.getBizVO().getLongitude()));
        deliveryOrderRequestDto.setStoreLat(new BigDecimal(storeInfo.getBizVO().getLatitude()));
        deliveryOrderRequestDto.setStorePhone(storeInfo.getBizVO().getPhone());
        deliveryOrderRequestDto.setStoreName(order.getShopName());
        deliveryOrderRequestDto.setCityName(storeInfo.getBizVO().getCity());
        deliveryOrderRequestDto.setReceiverName(order.getUserName());
        deliveryOrderRequestDto.setReceiverPrimaryPhone(order.getPhone());
        deliveryOrderRequestDto.setReceiverAddress(order.getAddress());
        deliveryOrderRequestDto.setReceiverLng(new BigDecimal(order.getLongitude()));
        deliveryOrderRequestDto.setReceiverLat(new BigDecimal(order.getLatitude()));
        deliveryOrderRequestDto.setOrderTime(new Date(order.getGmtCreate()));
        deliveryOrderRequestDto.setCallbackUrl(deliveryCallBackUrl);
        // 预约单预计送到时间
        deliveryOrderRequestDto.setExpectTime(new Date(order.getGmtCreate()));
        deliveryOrderRequestDto.setIsPre(order.getGmtExpect() != null ? 1 : 0);
        List<CreateDeliveryOrderRequestDto.DeliveryProductInfo> productInfos = new ArrayList<>();
        order.getProductList().forEach(productList -> {
            if (productList.getPrice() > 0) {
                CreateDeliveryOrderRequestDto.DeliveryProductInfo deliveryProductInfo = new CreateDeliveryOrderRequestDto.DeliveryProductInfo();
                deliveryProductInfo.setProductCode(productList.getProductId());
                deliveryProductInfo.setProductName(productList.getProductName());
                deliveryProductInfo.setProductNumber(productList.getNumber());
                deliveryProductInfo.setProductPrice(productList.getPrice().intValue());
                productInfos.add(deliveryProductInfo);
            }
        });
        deliveryOrderRequestDto.setProductInfos(productInfos);
        return deliveryOrderRequestDto;
    }
}
