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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
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.process.ResultCode;
import com.xxfc.platform.activity.feign.ActivityFeign;
import com.xxfc.platform.order.biz.*;
import com.xxfc.platform.order.contant.enumerate.ItemTypeEnum;
import com.xxfc.platform.order.contant.enumerate.OrderLogEnum;
import com.xxfc.platform.order.entity.OrderItem;
import com.xxfc.platform.order.entity.OrderRentVehicleDetail;
import com.xxfc.platform.order.pojo.order.DelayRentOrderDTO;
import com.xxfc.platform.order.pojo.order.OrderPageVO;
import com.xxfc.platform.order.pojo.order.VehicleItemDTO;
import com.xxfc.platform.order.pojo.price.DelayAddPriceVO;
import com.xxfc.platform.tour.feign.TourFeign;
import com.xxfc.platform.universal.constant.DictionaryKey;
import com.xxfc.platform.universal.entity.Dictionary;
import com.xxfc.platform.universal.feign.ThirdFeign;
import com.xxfc.platform.vehicle.common.RestResponse;
import com.xxfc.platform.vehicle.feign.VehicleFeign;
import com.xxfc.platform.vehicle.pojo.BookVehicleVO;
import com.xxfc.platform.vehicle.pojo.dto.order.VMCalendarPriceCostDTO;
import lombok.extern.slf4j.Slf4j;
import org.mockito.internal.util.collections.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

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

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

    @Autowired
    BaseOrderBiz baseOrderBiz;

    @Autowired
    OrderItemBiz orderItemBiz;

    @Autowired
    OrderMemberDetailBiz orderMemberDetailBiz;

    @Autowired
    OrderTourDetailBiz orderTourDetailBiz;

    @Autowired
    OrderRentVehicleBiz orderRentVehicleBiz;

    @Autowired
    OrderMsgBiz orderMsgBiz;

    @Autowired
    OrderCalculateBiz orderCalculateBiz;

    @Autowired
    OrderAccountBiz orderAccountBiz;

    @Autowired
    OrderTemplateBiz orderTemplateBiz;

    @Autowired
    OrderLogBiz orderLogBiz;

    @Autowired
    UserFeign userFeign;

    @Autowired
    VehicleFeign vehicleFeign;

    @Autowired
    TourFeign tourFeign;

    @Autowired
    ThirdFeign thirdFeign;

    @Autowired
    ActivityFeign activityFeign;

    public void delayRentOrder(OrderPageVO orderPageVO, DelayRentOrderDTO dto) {
        OrderRentVehicleDetail orvd = orderPageVO.getOrderRentVehicleDetail();
        OrderRentVehicleDetail oldOrvd = BeanUtil.toBean(orvd, OrderRentVehicleDetail.class);
        Integer delayAddDays = 0;
        Integer delayAddFreeDays = 0;
        //分布式事务执行标记
        Integer cloudTransact = 0;

        //计算delay多少天
        delayAddDays = orderCalculateBiz.getIncludeDays(orvd.getStartTime(), dto.getDelayEndTime());
        delayAddDays = delayAddDays - orderPageVO.getOrderRentVehicleDetail().getDayNum();

        //判断
        if(delayAddDays < 0) {
            throw new BaseException(ResultCode.PARAM_ILLEGAL_CODE, Sets.newSet("延期时间不对"));
        }else {
            //变化的延期免费天数
            Integer changeDelayFreeDays = 0;
            List<VMCalendarPriceCostDTO> delayAmountList;

            if(delayAddDays > 0) {
                VehicleItemDTO vehicleItemDTO = BeanUtil.toBean(orderItemBiz.selectOne(new OrderItem(){{
                    setType(ItemTypeEnum.VEHICLE_MODEL.getCode());
                    setOrderId(orderPageVO.getId());
                }}), VehicleItemDTO.class);
                List<VMCalendarPriceCostDTO> vmcpcds = vehicleItemDTO.getVehicleDetail();

                //获得延期天数费用
                delayAmountList = orderItemBiz.getOverAmountList(vmcpcds.get(vmcpcds.size() - 1).getDate(), delayAddDays, orvd.getModelId(), orderPageVO.getUserId());
                //处理免费天数和免费金额
                delayAmountList.parallelStream().forEach( vmcpcd -> {
                    vmcpcd.setValidFreeDays(vmcpcd.getFreeDays());
                    vmcpcd.setFreeAmount(vmcpcd.getPrice());
                });

                delayAddFreeDays = delayAmountList.parallelStream().mapToInt(VMCalendarPriceCostDTO::getFreeDays).sum();
            }else {
                delayAmountList = CollUtil.newArrayList();
                delayAddFreeDays = 0;
            }

            //初始化变化的延期免费天数为延期天数
            changeDelayFreeDays = delayAddFreeDays;

            //判断是否已经设置了延期, 修改变化的延期免费天数
            if(orvd.getDelayAddDays() > 0) {
                //extendDelayDays = delayAddDays - orvd.getDelayAddDays();
                changeDelayFreeDays = delayAddFreeDays - orvd.getDelayAddFreeDays();
            }

            //根据 changeDelayFreeDays 判断 是否拥有那么足够的天数
            if(changeDelayFreeDays > 0) {
                AppUserDTO appUserDTO = userFeign.userDetailById(orderPageVO.getUserId()).getData();
                if(appUserDTO.getRentFreeDays() < changeDelayFreeDays) {
                    throw new BaseException(ResultCode.FAILED_CODE, Sets.newSet("免费天数不够"));
                }
            }

            //触发调用修改预约
            dto.setEndTime(dto.getDelayEndTime());
            dto.setStartTime(orderPageVO.getOrderRentVehicleDetail().getStartTime());

            //根据订单号获取订单
            RestResponse restResponse = vehicleFeign.updateOrderBookRecord(new BookVehicleVO() {{
                setVehicleId(orderPageVO.getOrderRentVehicleDetail().getVehicleId());
                setVehicleBookRecordId(orvd.getBookRecordId());
                setBookStartDate(dto.getBookStartDateTime());
                setBookEndDate(dto.getBookEndDateTime());
                setBookStartDateTime(dto.getBookStartDateTime());
                setBookEndDateTime(dto.getBookEndDateTime());
                setBookType(BOOK_TYPE_RENT);
            }});

            if( !SYS_JSON_TRUE.equals(restResponse.getStatus())) {
                throw new BaseException(ResultCode.FAILED_CODE, Sets.newSet("延期失败"));
            }
            cloudTransact = 1;

            //扣减免费天数
            if(changeDelayFreeDays > 0) {
                int result = userFeign.memberDays(orderPageVO.getUserId(), changeDelayFreeDays, UserFeign.MEMBER_DAYS_LOCK);
                if (result < 0) {
                    throw new BaseException(ResultCode.FAILED_CODE);
                }
            }else if(changeDelayFreeDays < 0){
                int result = userFeign.memberDays(orderPageVO.getUserId(), 0 - changeDelayFreeDays, UserFeign.MEMBER_DAYS_WITHDRAW);
                if (result < 0) {
                    throw new BaseException(ResultCode.FAILED_CODE);
                }
            }
            cloudTransact = 2;

            //更新OrderRentVehicleDetail
            Map<String, Dictionary> dictionaryMap = thirdFeign.dictionaryGetAll4Map().getData();
            orvd.setDelayAddDamageSafe(dto.getNeedDamageSafe());
            orvd.setDelayAddDays(delayAddDays);
            orvd.setDelayAddFreeDays(delayAddFreeDays);
            orvd.setDelayAddEndTime(dto.getDelayEndTime());
            //修改还车时间
            orvd.setEndTime(dto.getDelayEndTime());
            DelayAddPriceVO delayAddPriceVO = new DelayAddPriceVO(){{
                setDamageSafePrice(new BigDecimal(dictionaryMap.get(APP_ORDER+ "_"+ DictionaryKey.DAMAGE_SAFE).getDetail()));
                setDelayAddDays(orvd.getDelayAddDays());
                setDelayAmountList(delayAmountList);
            }};

            if(SYS_TRUE.equals(dto.getNeedDamageSafe())) {
                delayAddPriceVO.initDelayDamageSafeAmount();
            }
            orvd.setDelayAddDetail(JSONUtil.toJsonStr(delayAddPriceVO));
            orderRentVehicleBiz.updateSelectiveByIdRe(orvd);
            orderLogBiz.logChange(orvd, oldOrvd, dto.getOperateId(), orderPageVO.getNo(), OrderLogEnum.DELAY_MODIFY);
        }
    }
}