package cn.freemud.service.impl;

import cn.freemud.adapter.SpellGroupOrderAdapter;
import cn.freemud.amqp.Header;
import cn.freemud.amqp.MQAction;
import cn.freemud.amqp.MQMessage;
import cn.freemud.amqp.MQService;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.base.util.DateUtil;
import cn.freemud.entities.dto.ActivityCalculationDiscountResponseDto;
import cn.freemud.entities.dto.CreateSpellGroupOrderDto;
import cn.freemud.entities.dto.delivery.QueryDeliveryTemplateRequest;
import cn.freemud.entities.dto.delivery.QueryDeliveryTemplateResponse;
import cn.freemud.entities.dto.ecology.VirtualBindStoreResponse;
import cn.freemud.entities.dto.order.CreatePrepayRequestDto;
import cn.freemud.entities.dto.product.ProductInfo;
import cn.freemud.entities.dto.promotion.CalculationDiscountRequestDto;
import cn.freemud.entities.dto.promotion.QuerySpellGroupVoResponse;
import cn.freemud.entities.vo.CreateSpellGroupOrderReq;
import cn.freemud.enums.ActivityGroupStatusEnum;
import cn.freemud.enums.ResponseResult;
import cn.freemud.manager.SpellGroupOrderDataManager;
import cn.freemud.service.SpellGroupOrderService;
import cn.freemud.utils.ResponseUtil;
import com.freemud.api.assortment.datamanager.entity.vo.AssortmentCustomerInfoVo;
import com.freemud.api.assortment.datamanager.manager.customer.AssortmentCustomerInfoManager;
import com.freemud.application.sdk.api.log.ErrorLog;
import com.freemud.application.sdk.api.log.LogThreadLocal;
import com.freemud.application.sdk.api.ordercenter.entities.v1.OrderBeanV1;
import com.freemud.application.sdk.api.ordercenter.enums.AfterSalesType;
import com.freemud.application.sdk.api.ordercenter.request.OrderCancelReq;
import com.freemud.application.sdk.api.ordercenter.request.create.OrderTaskReq;
import com.freemud.application.sdk.api.ordercenter.response.OrderBaseResp;
import com.freemud.application.sdk.api.ordercenter.response.orderInfo.OrderInfoReqs;
import com.freemud.application.sdk.api.ordercenter.service.OrderSdkService;
import com.freemud.application.sdk.api.promotioncenter.request.promotion.ActivityUpdateStockRequest;
import com.freemud.application.sdk.api.promotioncenter.service.PromotionSdkService;
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.adapter.OrderSdkAdapter;
import com.freemud.sdk.api.assortment.order.enums.AutoOrderConfigTime;
import com.freemud.sdk.api.assortment.order.request.order.CancelOrderRequest;
import com.freemud.sdk.api.assortment.order.request.order.OrderStatusChangeRequestDto;
import com.freemud.sdk.api.assortment.order.response.order.BaseOrderResponse;
import com.freemud.sdk.api.assortment.order.response.order.CreateOrderResponse;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Random;

import static com.freemud.sdk.api.assortment.order.domain.ResponseCodeConstant.RESPONSE_SUCCESS;
import static com.freemud.sdk.api.assortment.order.domain.ResponseCodeConstant.RESPONSE_SUCCESS_STR;


/**
 * @author wanghanghang
 * @title: SpellGroupOrderServiceImpl
 * @projectName order-group
 * @description: 拼团业务层Service
 * @date 2021/4/16上午9:47
 */

@Service
public class SpellGroupOrderServiceImpl implements SpellGroupOrderService {
    @Autowired
    private SpellGroupOrderAdapter spellGroupOrderAdapter;

    @Autowired
    private OrderSdkAdapter orderSdkAdapter;

    @Autowired
    private SpellGroupOrderDataManager spellGroupOrderDataManager;

    @Autowired
    private AssortmentCustomerInfoManager customerInfoManager;

    @Autowired
    private OrderSdkService orderSdkService;

    @Autowired
    private OrderServiceImpl orderService;

    @Autowired
    private PromotionSdkService promotionSdkService;

    @Autowired
    private StoreCenterService storeCenterService;

    @Autowired
    private MQService mqService;


    @Autowired
    private PayServiceImpl payServiceimpl;


    @Value("${program.backorders_change_order_status_consumer_queue}")
    private String backOrdersChangeOrderStatusConsumerQueue;
    @Value("${program.backorders_notify_activity_exchange}")
    private String backOrdersNotifyActivityExchange;

    @Override
    public BaseResponse createSpellGroupOrder(CreateSpellGroupOrderReq createSpellGroupOrderReq) {
        String trackingNo = LogThreadLocal.getTrackingNo();
        AssortmentCustomerInfoVo userLoginInfoDto = customerInfoManager.getCustomerInfoByObject(createSpellGroupOrderReq.getSessionId());
        if (userLoginInfoDto == null || StringUtils.isEmpty(userLoginInfoDto.getMemberId())) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        /*团id不为空，查询团信息，校验团状态是否正常.调用促销查询团是否关闭,关闭之后给提示不可下单*/
        if(!StringUtils.isEmpty(createSpellGroupOrderReq.getSpellGroupCode())){
            QuerySpellGroupVoResponse querySpellGroupVoResponse = spellGroupOrderDataManager.queryByGroupIdNew(createSpellGroupOrderReq.getSpellGroupCode(),
                    userLoginInfoDto.getMemberId(),createSpellGroupOrderReq.getActivityCode(),createSpellGroupOrderReq.getPartnerId());
            if(!ResponseResult.SUCCESS.getCode().equals(querySpellGroupVoResponse.getStatusCode()) || querySpellGroupVoResponse.getResult() == null){
                return ResponseUtil.error(querySpellGroupVoResponse.getStatusCode(),querySpellGroupVoResponse.getMsg());
            }
            if(!ActivityGroupStatusEnum.NORMAL.getCode().equals(querySpellGroupVoResponse.getResult().getActivityGroupStatus())){
                String message = ActivityGroupStatusEnum.getByCode(querySpellGroupVoResponse.getResult().getActivityGroupStatus()).getDesc();
                return ResponseUtil.error(message);
            }
        }
        /*初始化service业务DTO类，后续数据收集以及转换依据CreateSpellGroupOrderDto*/
        CreateSpellGroupOrderDto createSpellGroupOrderDto = new CreateSpellGroupOrderDto();
        BeanUtils.copyProperties(createSpellGroupOrderReq, createSpellGroupOrderDto);
        /*前端传入地址等信息->转换至DTO*/
        spellGroupOrderAdapter.convertToReceiveAddress(createSpellGroupOrderDto);
        createSpellGroupOrderDto.setUserId(userLoginInfoDto.getMemberId());
        createSpellGroupOrderDto.setNickName(userLoginInfoDto.getNickName());
        /*获取虚拟门店id,拼单虚拟门店，无需校验。方便后续取值门店名称以及门店英文名称*/
        VirtualBindStoreResponse virtualBindStoreResponse = spellGroupOrderDataManager.change2BindMallShopId(createSpellGroupOrderReq.getAppId());
        if(virtualBindStoreResponse == null){
            return ResponseUtil.error(ResponseResult.SPELL_GROUP_QUERY_BIND_STORE_ERROR);
        }
        createSpellGroupOrderDto.setStoreId(virtualBindStoreResponse.getStoreId());
        /*门店信息->转换至DTO*/
        StoreResponse storeResponse = spellGroupOrderDataManager.getStoreInfo(createSpellGroupOrderReq.getPartnerId(), virtualBindStoreResponse.getStoreId(), trackingNo);
        if(storeResponse == null || storeResponse.getBizVO() == null){
           return ResponseUtil.error(ResponseResult.STORE_ITEM_QUERY_ERROR);
        }
        createSpellGroupOrderDto.setStore(storeResponse.getBizVO());
        /*查询拼团商品信息->转换至DTO*/
        List<ProductInfo> productInfosDto = spellGroupOrderDataManager.queryProductInfos(createSpellGroupOrderDto);
        if(productInfosDto == null){
            return ResponseUtil.error(ResponseResult.SPELL_GROUP_QUERY_PRODUCT_INFOS_ERROR);
        }
        createSpellGroupOrderDto.setProducts(productInfosDto);
        /*根据商品信息查询促销，获取商品价格等信息->转换促销结算信息*/
        CalculationDiscountRequestDto calculationDiscountRequestDto = spellGroupOrderAdapter.convertToCalculationDiscountRequestDto(createSpellGroupOrderDto, userLoginInfoDto);
        ActivityCalculationDiscountResponseDto activityCalculationDiscountResponseDto = spellGroupOrderDataManager.queryCalculationDiscount(calculationDiscountRequestDto);
        if(ResponseResult.PARTICIPATE_IN_THE_GROUP_OVERRUN.getCode().equals(activityCalculationDiscountResponseDto.getStatusCode())){
            return ResponseUtil.error(ResponseResult.PARTICIPATE_IN_THE_GROUP_OVERRUN);
        }
        if (!ResponseResult.SUCCESS.getCode().equals(activityCalculationDiscountResponseDto.getStatusCode()) || activityCalculationDiscountResponseDto.getResult() == null) {
            return ResponseUtil.error(ResponseResult.SPELL_GROUP_QUERY_CALCULATION_DISCOUNT_ERROR);
        }
        //促销和产品给出规则，如果促销返回的价格是商品原价，则表示库存不足或者活动关闭  肯定：拼团的商品价格，肯定比商品原价低
        if (activityCalculationDiscountResponseDto.getResult().getTotalAmount().equals(productInfosDto.get(0).getOriginalPrice())) {
            return ResponseUtil.error(ResponseResult.SPELL_GROUP_ACTIVITE_AMOUNT_ERROR);
        }
        createSpellGroupOrderDto.setCalculationDiscount(activityCalculationDiscountResponseDto.getResult());
        /*转换request->查询快递费用信息->转换dto*/
        QueryDeliveryTemplateRequest queryDeliveryTemplateRequest = spellGroupOrderAdapter.convertToQueryDeliveryTemplateRequest(createSpellGroupOrderDto);
        QueryDeliveryTemplateResponse queryDeliveryTemplateResponse = spellGroupOrderDataManager.queryDeliveryTemplate(queryDeliveryTemplateRequest);
        if(queryDeliveryTemplateResponse == null ){
            return ResponseUtil.error(ResponseResult.SPELL_GROUP_QUERY_DELIVERYTEMPLATE_ERROR);
        }
        createSpellGroupOrderDto.setDeliveryTemplateInfo(queryDeliveryTemplateResponse.getData());


//        QueryDeliveryTemplateResponse.DeliveryTemplateInfoVo deliveryTemplateInfoVo = new QueryDeliveryTemplateResponse.DeliveryTemplateInfoVo();
//        deliveryTemplateInfoVo.setFreight(1L);
//        deliveryTemplateInfoVo.setIsDispatchFree(false);
//        createSpellGroupOrderDto.setDeliveryTemplateInfo(deliveryTemplateInfoVo);

        /*createSpellGroupOrderDto转换为订单Request信息*/
        com.freemud.application.sdk.api.ordercenter.request.create.CreateOrderRequest createOrderRequest = spellGroupOrderAdapter.convertToCreateOrderRequest(createSpellGroupOrderDto, userLoginInfoDto);
        OrderBaseResp<OrderInfoReqs> response = orderSdkService.createOrder(createOrderRequest, trackingNo);
        CreateOrderResponse createOrderResponse = orderSdkAdapter.convent2NEWOrderInfoReqs(response);
        if (createOrderResponse == null || !ResponseResult.SUCCESS.getCode().equals(createOrderResponse.getErrcode().toString()) || createOrderResponse.getData() == null) {
            return ResponseUtil.error(ResponseResult.SPELL_GROUP_CREAT_ORDER_ERROR);
        }
        /*调用活动库存*/
        BaseOrderResponse baseOrderResponse = updateActivityStock(createOrderResponse.getData(), createSpellGroupOrderDto);
        if (!RESPONSE_SUCCESS.equals(baseOrderResponse.getErrcode())) {
            return ResponseUtil.error(baseOrderResponse.getErrcode().toString(), baseOrderResponse.getErrmsg(), null);
        }
        /*创建支付*/
        CreatePrepayRequestDto createPrepayRequestDto = spellGroupOrderAdapter.convertToCreatePrepayRequest(userLoginInfoDto, createOrderResponse.getData(), trackingNo,createSpellGroupOrderDto.getProvince());
        return ResponseUtil.success(payServiceimpl.createPrepayOrder(createPrepayRequestDto));
    }

    /***
     * 查询配送费。包装一层返回给前端。
     * @param request
     * @return
     */
    @Override
    public BaseResponse queryDeliveryAmount(QueryDeliveryTemplateRequest request) {
        QueryDeliveryTemplateResponse queryDeliveryTemplateResponse = spellGroupOrderDataManager.queryDeliveryTemplate(request);
        if(queryDeliveryTemplateResponse == null){
            return ResponseUtil.error(ResponseResult.SPELL_GROUP_QUERY_DELIVERYTEMPLATE_ERROR);
        }
        QueryDeliveryTemplateResponse.DeliveryTemplateInfoVo deliveryTemplateInfoVo = queryDeliveryTemplateResponse.getData();
        if (deliveryTemplateInfoVo!= null && deliveryTemplateInfoVo.getCostType().compareTo(0) !=0) {
            deliveryTemplateInfoVo.setFreight(0);
        }
//        QueryDeliveryTemplateResponse.DeliveryTemplateInfoVo deliveryTemplateInfoVo = new QueryDeliveryTemplateResponse.DeliveryTemplateInfoVo();
//        deliveryTemplateInfoVo.setFreight(1L);
//        deliveryTemplateInfoVo.setIsDispatchFree(false);
        return ResponseUtil.success(deliveryTemplateInfoVo);
    }

    /**
     * 扣减动库存
     * @param orderBean
     * @param createSpellGroupOrderDto
     * @return
     */
    private BaseOrderResponse updateActivityStock(OrderBeanV1 orderBean, CreateSpellGroupOrderDto createSpellGroupOrderDto) {
        ActivityUpdateStockRequest activityUpdateStockRequest = spellGroupOrderAdapter.convert2ActivityUpdateStockRequest(orderBean, createSpellGroupOrderDto);
        if (activityUpdateStockRequest != null && (CollectionUtils.isNotEmpty(activityUpdateStockRequest.getStock()) || CollectionUtils.isNotEmpty(activityUpdateStockRequest.getActivityList()))) {
            com.freemud.application.sdk.api.base.BaseResponse activityResponse = promotionSdkService.subtractStock(activityUpdateStockRequest, "");
//            ThirdPartyLog.infoConvertJson(System.currentTimeMillis(), System.currentTimeMillis(),
//                    "subtractStock", JSONObject.toJSONString(activityUpdateStockRequest), JSONObject.toJSONString(activityResponse));
            if (!ObjectUtils.equals(RESPONSE_SUCCESS_STR, activityResponse.getCode())) {
                //TODO 失败取消订单,异步冲正库存
                CancelOrderRequest cancelOrderRequest = orderSdkAdapter.convent2CancelOrderRequest(orderBean.getOid(), orderBean.getCompanyId(),
                        AfterSalesType.SYSTEM_CANCEL, "活动库存不足", "", null);
                orderCancel(cancelOrderRequest);
                //失败异步冲正库存，取消订单
                backOrdersNotifyActivity(orderBean, backOrdersChangeOrderStatusConsumerQueue, backOrdersNotifyActivityExchange);
                return BaseOrderResponse.getErrorBaseOrderResponse(activityResponse.getCode(), "活动库存不足");
            }
        }
        return BaseOrderResponse.getErrorBaseOrderResponse(RESPONSE_SUCCESS_STR, "");
    }

    public BaseOrderResponse orderCancel(CancelOrderRequest cancelOrderRequest) {
        OrderCancelReq request = new OrderCancelReq();
        //商户号必传
        request.setPartnerId(cancelOrderRequest.getPartnerId());
        request.setOrderCode(cancelOrderRequest.getOrderId());
        request.setReqRemark(cancelOrderRequest.getReqRemark());
        //售后单类型 1:其他取消 2:用户取消 3:商户取消 4:未支付超时关单 5:商户接单超时取消 6:商家拒单
        // 7:配送用户拒收 8:用户售后退货/售后退款 9:系统取消 10:客服取消 11:用户统一取消，
        request.setAfterSalesType(cancelOrderRequest.getAfterSalesType().getIndex() == null ? 1 : cancelOrderRequest.getAfterSalesType().getIndex());
        request.setOrderClient(cancelOrderRequest.getOrderClient());
        request.setCancelReason(cancelOrderRequest.getReason());
        request.setAfterSalesReason(cancelOrderRequest.getReason());
        //若为4，默认做【创建】+【同意并退款完成】，售后单状态为【完成】
        request.setCreateEvent(cancelOrderRequest.getCreateEvent());
        request.setAfterSerialNo(cancelOrderRequest.getRefundSerialNo());
        request.setOperator(cancelOrderRequest.getOperator());
        //为空发起售后单
        if (cancelOrderRequest.getCreateEvent() == null) {
            // 查询门店服务配置，退单模式为2为自动退款，判断自动退款时间,设置为0则不传入timeout,
            StoreResponse.Configuration configuration = getStoreAutoConfiguration(cancelOrderRequest.getPartnerId(), cancelOrderRequest.getStoreId(), cancelOrderRequest.getTrackingNo());
            if (configuration != null && ObjectUtils.equals("2", configuration.getAutoChargebackOrderType())
                    && !ObjectUtils.equals("0", configuration.getAutoChargebackOrderTime())) {
                request.setTimeOut(AutoOrderConfigTime.getTime(configuration.getAutoChargebackOrderTime()));
            }
            OrderTaskReq orderTask = setAfterSalesOrderTimeOutTask(configuration);
            request.setOrderTask(orderTask);
        }
        request.setRefundDeliveryAmount(cancelOrderRequest.isRefundDeliveryAmount());
        OrderBaseResp response = orderSdkService.cancelOrder(request, cancelOrderRequest.getTrackingNo());
        return orderSdkAdapter.convent2BaseOrderResponse(response);
    }

    /**
     * 获取门店自动配置信息
     *
     * @param partnerId
     * @param storeCode
     * @param trackingNo
     * @return
     */
    private StoreResponse.Configuration getStoreAutoConfiguration(String partnerId, String storeCode, String trackingNo) {
        if (StringUtils.isEmpty(storeCode)) {
            return null;
        }
        StoreInfoRequest storeInfoRequest = new StoreInfoRequest();
        storeInfoRequest.setPartnerId(partnerId);
        storeInfoRequest.setStoreCode(storeCode);
        StoreResponse storeResponse = storeCenterService.getStoreInfo(storeInfoRequest, trackingNo);
        if (storeResponse == null || storeResponse.getBizVO() == null || storeResponse.getBizVO().getStoreConfig() == null) {
            return null;
        }
        return storeResponse.getBizVO().getStoreConfig();
    }

    /**
     * 设置申请退款时间
     * 如果时间的类型是2表示采用原来的48小时逻辑
     * 如果时间的类型是1表示在指定的时间之后进行退款
     * 为了防止同一时刻的退款量太大，需要将退款的订单分散到指定的时间后半小时内
     */
    private OrderTaskReq setAfterSalesOrderTimeOutTask(StoreResponse.Configuration configuration) {
        if (configuration == null) {
            return null;
        }
        if ((configuration.getTimeTypeOfRefund() != null && 2 == configuration.getTimeTypeOfRefund().intValue()) || configuration.getTimeTypeOfRefund() == null) {// 48小时之后
            OrderTaskReq orderTask = new OrderTaskReq();
            orderTask.setTaskType(4);
            orderTask.setTimeout(1);
            //1000*60*60*24*2 毫秒（48小时）
            long timeout = 172800000;
            long timeMillis = System.currentTimeMillis();
            Date processingDate = new Date(timeMillis + timeout - 60000);
            Date taskTime = new Date(timeMillis + timeout);
            orderTask.setTaskTime(DateUtil.convert2String(taskTime, DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
            //处理时间，当前时间加48小时减1分钟
            orderTask.setProcessingTime(DateUtil.convert2String(processingDate, DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
            return orderTask;
        } else if (configuration.getTimeTypeOfRefund() != null && 1 == configuration.getTimeTypeOfRefund().intValue()) {// 指定时间
            OrderTaskReq orderTask = new OrderTaskReq();
            orderTask.setTaskType(4);
            orderTask.setTimeout(1);
            // 获取门店配置的当天指定的退款时间
            String timeOfRefund = configuration.getTimeOfRefund();
            // 获取半小时的随机数
            Random r = new Random();
            int minute = r.ints(1, 31).findFirst().getAsInt() * 60000;
            String today = DateUtil.getCurrentDate(DateUtil.FORMAT_YMD);

            Date configTime = DateUtil.convert2Date(today + " " + timeOfRefund, DateUtil.FORMAT_YYYY_MM_DD_HHMMSS);
            // 判断当前时间是否已经超过门店设置的截至时间
            if (new Date().after(configTime)) {
                today = DateUtil.convert2String(DateUtil.addDays(new Date(), 1), DateUtil.FORMAT_YMD);
                configTime = DateUtil.convert2Date(today + " " + timeOfRefund, DateUtil.FORMAT_YYYY_MM_DD_HHMMSS);
            }
            Date processingDate = new Date(configTime.getTime() + minute);
            String processingStr = DateUtil.convert2String(processingDate, DateUtil.FORMAT_YYYY_MM_DD_HHMMSS);
            orderTask.setTaskTime(processingStr);
            orderTask.setProcessingTime(processingStr);
            return orderTask;
        }
        return null;
    }


    private void backOrdersNotifyActivity(OrderBeanV1 orderBean, String backOrdersChangeOrderStatusConsumerQueue, String backOrdersNotifyActivityExchange) {
        if (null == orderBean || backOrdersChangeOrderStatusConsumerQueue == null || backOrdersNotifyActivityExchange == null) {
            return;
        }
        String oid = orderBean.getOid();
        Integer status = orderBean.getStatus();
        if (StringUtils.isEmpty(oid)) {
            return;
        }
//        AppLogUtil.infoLog("backOrdersStatusChange", oid, String.valueOf(status));
        OrderStatusChangeRequestDto requestDto = new OrderStatusChangeRequestDto();
        requestDto.setOid(oid);
        requestDto.setOrderStatus(status);
        try {
            Header header = new Header(MQAction.INSERT.getAction(), "backOrdersStatusChange", oid, backOrdersChangeOrderStatusConsumerQueue);
            MQMessage<OrderStatusChangeRequestDto> message = new MQMessage<>(header, requestDto);
            mqService.convertAndSend(backOrdersNotifyActivityExchange, backOrdersChangeOrderStatusConsumerQueue, message);
        } catch (Exception e) {
            ErrorLog.printErrorLog("backOrdersStatusChangeNotify_error","backOrdersStatusChangeNotify",requestDto,e);
        }
    }


}
