package com.xxfc.platform.order.biz.inner;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.github.wxiaoqi.security.admin.feign.UserFeign;
import com.github.wxiaoqi.security.admin.feign.dto.AppUserDTO;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.github.wxiaoqi.security.common.util.IntervalUtil;
import com.github.wxiaoqi.security.common.util.process.ResultCode;
import com.xxfc.platform.order.biz.*;
import com.xxfc.platform.order.contant.enumerate.OrderStatusEnum;
import com.xxfc.platform.order.contant.enumerate.OrderTypeEnum;
import com.xxfc.platform.order.contant.enumerate.RefundStatusEnum;
import com.xxfc.platform.order.contant.enumerate.RefundTypeEnum;
import com.xxfc.platform.order.entity.*;
import com.xxfc.platform.order.pojo.mq.OrderMQDTO;
import com.xxfc.platform.tour.feign.TourFeign;
import com.xxfc.platform.universal.dto.SmsTemplateDTO;
import com.xxfc.platform.universal.entity.Dictionary;
import com.xxfc.platform.universal.feign.ThirdFeign;
import com.xxfc.platform.universal.vo.OrderRefundVo;
import com.xxfc.platform.vehicle.common.RestResponse;
import com.xxfc.platform.vehicle.feign.VehicleFeign;
import com.xxfc.platform.vehicle.pojo.CompanyDetail;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.jexl2.MapContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

import static com.github.wxiaoqi.security.common.constant.CommonConstants.SYS_FALSE;
import static com.github.wxiaoqi.security.common.constant.CommonConstants.SYS_TRUE;
import static com.xxfc.platform.universal.constant.DictionaryKey.*;

/**
 * 订单退款记录表
 *
 * @author zjw
 * @email nishijjo@qq.com
 * @date 2019-06-18 11:08:09
 */
@Slf4j
@Service
public class OrderCancelBiz {

    @Autowired
    BaseOrderBiz baseOrderBiz;

    @Autowired
    OrderMemberDetailBiz orderMemberDetailBiz;

    @Autowired
    OrderTourDetailBiz orderTourDetailBiz;

    @Autowired
    OrderRentVehicleBiz orderRentVehicleBiz;

    @Autowired
    OrderRefundBiz orderRefundBiz;

    @Autowired
    OrderMsgBiz orderMsgBiz;

    @Autowired
    UserFeign userFeign;

    @Autowired
    VehicleFeign vehicleFeign;

    @Autowired
    TourFeign tourFeign;

    @Autowired
    ThirdFeign thirdFeign;

    private static Map<Integer, List<Integer>> cancelAble;
    static {
        cancelAble = new HashMap<Integer, List<Integer>>();
        cancelAble.put(OrderTypeEnum.RENT_VEHICLE.getCode(), new LinkedList<Integer>(){{
            add(OrderStatusEnum.ORDER_UNPAY.getCode());
            add(OrderStatusEnum.ORDER_TOSTART.getCode());
        }});
        cancelAble.put(OrderTypeEnum.TOUR.getCode(), new LinkedList<Integer>(){{
            add(OrderStatusEnum.ORDER_UNPAY.getCode());
            add(OrderStatusEnum.ORDER_TOSTART.getCode());
        }});
        cancelAble.put(OrderTypeEnum.MEMBER.getCode(), new LinkedList<Integer>(){{
            add(OrderStatusEnum.ORDER_UNPAY.getCode());
        }});
    }

    /**
     * 取消订单
     * @param baseOrder
     */
    @Transactional
    public void cancel(BaseOrder baseOrder) {
        OrderRentVehicleDetail orvd = new OrderRentVehicleDetail();
        OrderTourDetail otd = new OrderTourDetail();
        OrderMemberDetail omd = new OrderMemberDetail();
        if(cancelAble.get(baseOrder.getType()).contains(baseOrder.getStatus())) {
            BaseOrder updateOrder = new BaseOrder(){{
                setId(baseOrder.getId());
                setStatus(OrderStatusEnum.ORDER_CANCEL.getCode());
                setCancelReason(baseOrder.getCancelReason());
                setVersion(baseOrder.getVersion());
            }};
            BaseOrder hasUpdateOrder = baseOrderBiz.updateSelectiveByIdReT(updateOrder);

            //触发退款流程
            //判断是否已支付
            if(SYS_TRUE.equals(baseOrder.getHasPay())) {
                //判断订单类型
                if(OrderTypeEnum.RENT_VEHICLE.getCode().equals(baseOrder.getType())) {
                    orvd = orderRentVehicleBiz.selectOne(new OrderRentVehicleDetail(){{
                        setOrderId(baseOrder.getId());
                    }});

                    //如果超过出发时间，不能取消订单
                    //根据时间处理goodsAmount
                    //获取出发时间 到现在 距离时间
                    Long timeLag = orvd.getStartTime() - System.currentTimeMillis();
                    if(timeLag < 0) {
                        throw new BaseException(ResultCode.FAILED_CODE, new HashSet<String>(){{
                            add("已超过出发时间，不能取消订单");
                        }});
                    }

                    //退款流程
                    orderRefundBiz.rentRefundProcess(hasUpdateOrder, orvd.getDeposit(), timeLag, APP_ORDER+ "_"+ RENT_REFUND);

                    //已付款的取消订单发送消息
                    try {
                        AppUserDTO appUserDTO = userFeign.userDetailById(baseOrder.getUserId()).getData();
                        //处理后台用户提醒短信的发送
//                        orderMsgBiz.handelBgUserMsg4Pay(orvd, baseOrder, appUserDTO, OrderMsgBiz.RENT_CANCEL);
                        orderMsgBiz.handelMsgCancel(orvd, otd, omd, baseOrder, appUserDTO);
                    }catch (Exception e) {
                        log.error(e.getMessage(), e);
                    }

                }else if (OrderTypeEnum.TOUR.getCode().equals(baseOrder.getType())) {
                    otd = orderTourDetailBiz.selectOne(new OrderTourDetail(){{
                        setOrderId(baseOrder.getId());
                    }});
                    Long timeLag = otd.getStartTime() - System.currentTimeMillis();

                    //判断是省内还是省外
                    String key = TOUR_IN_REFUND;
                    if(SYS_TRUE.equals(otd.getIsOutside())) {
                        key = TOUR_REFUND;
                    }
                    //退款流程
                    orderRefundBiz.rentRefundProcess(hasUpdateOrder, timeLag, APP_ORDER+ "_"+ key);
                }
            }

            //处理取消流程
            if(OrderTypeEnum.RENT_VEHICLE.getCode().equals(baseOrder.getType())) {
                orvd = orderRentVehicleBiz.selectOne(new OrderRentVehicleDetail(){{
                    setOrderId(baseOrder.getId());
                }});

                //取消租车预定
                //已支付,并且是待出行状态，取消预约
                if(OrderStatusEnum.ORDER_TOSTART.equals(baseOrder.getType()) && SYS_TRUE.equals(baseOrder.getHasPay())){
                    vehicleFeign.unbookVehicle(orvd.getBookRecordId());
                }else {
                    //未支付，拒绝之前的预约
                    RestResponse<Integer> restResponse = vehicleFeign.rentRejectVehicleBooking(orvd.getBookRecordId());
                }

                //取消租车免费天数使用
                if(null != orvd.getFreeDays() && orvd.getFreeDays() > 0) {
                    int result = userFeign.memberDays(baseOrder.getUserId(), orvd.getFreeDays(), UserFeign.MEMBER_DAYS_WITHDRAW);
                    if(result < 0) {
                        throw new BaseException(ResultCode.FAILED_CODE);
                    }
                }
            }else if(OrderTypeEnum.TOUR.getCode().equals(baseOrder.getType())) {
                otd = orderTourDetailBiz.selectOne(new OrderTourDetail(){{
                    setOrderId(baseOrder.getId());
                }});

                //增加库存
                tourFeign.stock(otd.getSpePriceId(), otd.getTotalNumber(), TourFeign.STOCK_PLUS);
            }

            //发送队列消息
            baseOrderBiz.sendOrderMq(orvd, otd, omd, baseOrder, OrderMQDTO.ORDER_CANCEL);
        }else {
            throw new BaseException(ResultCode.FAILED_CODE);
        }
    }
}