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.order.CreatePrepayRequestDto;
import cn.freemud.entities.dto.product.ProductInfo;
import cn.freemud.entities.dto.promotion.CalculationDiscountRequestDto;
import cn.freemud.entities.dto.promotion.CalculationDiscountResponseDto;
import cn.freemud.entities.vo.CreateSpellGroupOrderReq;
import cn.freemud.enums.ResponseResult;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.manager.SpellGroupOrderDataManager;
import cn.freemud.service.SpellGroupOrderService;
import cn.freemud.utils.ResponseUtil;
import com.alibaba.fastjson.JSONObject;
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.ApiLog;
import com.freemud.application.sdk.api.log.LogThreadLocal;
import com.freemud.application.sdk.api.log.ThirdPartyLog;
import com.freemud.application.sdk.api.membercenter.response.QueryReceiveAddressResponse;
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.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.ActivitySdkAdapter;
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.*;
import com.freemud.sdk.api.assortment.order.response.order.BaseOrderResponse;
import com.freemud.sdk.api.assortment.order.response.order.CreateOrderResponse;
import com.freemud.sdk.api.assortment.order.response.order.QueryOrdersResponse;
import com.freemud.sdk.api.assortment.order.service.OrderCenterSdkService;
import com.freemud.sdk.api.assortment.order.service.order.OrderCenterSdkServiceImpl;
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 org.springframework.transaction.annotation.Transactional;

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 ActivitySdkAdapter activitySdkAdapter;

    @Autowired
    private MQService mqService;

    @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();
        /*校验用户信息*/
        String sessionId = createSpellGroupOrderReq.getSessionId();
        AssortmentCustomerInfoVo userLoginInfoDto = customerInfoManager.getCustomerInfoByObject(sessionId);
        if (userLoginInfoDto == null || StringUtils.isEmpty(userLoginInfoDto.getMemberId())) {
            throw new ServiceException(ResponseResult.NOT_LOGIN);
        }
        /*初始化service业务DTO类，后续数据转换依据createSpellGroupOrderDto*/
        CreateSpellGroupOrderDto createSpellGroupOrderDto = new CreateSpellGroupOrderDto();
        BeanUtils.copyProperties(createSpellGroupOrderReq, createSpellGroupOrderDto);
        createSpellGroupOrderDto.setUserId(userLoginInfoDto.getMemberId());
        createSpellGroupOrderDto.setNickName(userLoginInfoDto.getNickName());
        /*查询会员接口,获取城市等信息*/
        //todo
        /*获取门店信息,拼单虚拟门店，无需校验*/
        StoreResponse storeResponse = spellGroupOrderDataManager.getStoreInfo(createSpellGroupOrderReq.getPartnerId(), createSpellGroupOrderReq.getStoreId(), trackingNo);
         //门店信息->转换至DTO
        createSpellGroupOrderDto.setStoreResponse(storeResponse);
        /*团id不为空，调用促销查询团是否关闭,关闭之后给提示不可下单*/
        String getSpellGroupCode = createSpellGroupOrderReq.getSpellGroupCode();
//        if (1 == 1) {
//            return ResponseUtil.error(ResponseResult.SPELL_GROUP_THE_CLUB_IS_FULL);
//        }
        /*---------团开启 则继续执行-------*/
        /*查询配送地址等信息->转换至DTO*/
        QueryReceiveAddressResponse queryReceiveAddressResponse = spellGroupOrderDataManager.queryOrderReceiveAddress(createSpellGroupOrderReq.getReceiveId(), createSpellGroupOrderReq.getPartnerId(), trackingNo);
        spellGroupOrderAdapter.convertToReceiveAddress(queryReceiveAddressResponse, createSpellGroupOrderDto);
        /*查询商品信息*/
        List<ProductInfo> productInfosDto = spellGroupOrderDataManager.queryProductInfos(createSpellGroupOrderDto);
        createSpellGroupOrderDto.setProducts(productInfosDto);
        /*商品信息查询促销，获取商品价格等信息  转换结算信息*/
        CalculationDiscountRequestDto calculationDiscountRequestDto = spellGroupOrderAdapter.convertToCalculationDiscountRequestDto(createSpellGroupOrderDto, userLoginInfoDto);
        ActivityCalculationDiscountResponseDto activityCalculationDiscountResponseDto = spellGroupOrderDataManager.queryCalculationDiscount(calculationDiscountRequestDto);
        //促销和产品给出规则，如果促销返回的价格是商品原价，则表示库存不足或者活动关闭 == 拼团的商品价格，肯定比商品原价低
        if (activityCalculationDiscountResponseDto.getResult().getTotalAmount().equals(productInfosDto.get(0).getOriginalPrice())) {
//      todo      return ResponseUtil.error(ResponseResult.SPELL_GROUP_ACTIVITE_AMOUNT_ERROR);
        }
        createSpellGroupOrderDto.setActivityCalculationDiscountResponseDto(activityCalculationDiscountResponseDto);
        //转换类存入费用信息->配送费

        //转换费用信息

        //DTO转换为订单Request信息
        com.freemud.application.sdk.api.ordercenter.request.create.CreateOrderRequest createOrderRequest = spellGroupOrderAdapter.convertToCreateOrderRequest(createSpellGroupOrderDto, userLoginInfoDto);
        com.freemud.application.sdk.api.ordercenter.response.BaseResponse<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);
        return orderService.createPrepayOrder(createPrepayRequestDto);
    }

    /**
     * 扣减动库存
     * @param orderBean
     * @param createSpellGroupOrderDto
     * @return
     */
    private BaseOrderResponse updateActivityStock(QueryOrdersResponse.DataBean.OrderBean 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());
        com.freemud.application.sdk.api.ordercenter.response.BaseResponse 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(QueryOrdersResponse.DataBean.OrderBean 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;
        }
        ApiLog.info("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) {
            //TODO 邮件告警
            ThirdPartyLog.infoConvertJson(System.currentTimeMillis(), System.currentTimeMillis(),
                    "backOrdersStatusChangeNotify_error", backOrdersNotifyActivityExchange, backOrdersChangeOrderStatusConsumerQueue);
        }
    }


}
