package com.xxfc.platform.order.biz;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.wxiaoqi.security.admin.dto.UserMemberDTO;
import com.github.wxiaoqi.security.admin.feign.UserFeign;
import com.github.wxiaoqi.security.admin.feign.dto.AppUserDTO;
import com.github.wxiaoqi.security.admin.feign.dto.UserDTO;
import com.github.wxiaoqi.security.admin.feign.rest.UserRestInterface;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.github.wxiaoqi.security.common.context.BaseContextHandler;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.util.Query;
import com.github.wxiaoqi.security.common.util.process.ResultCode;
import com.github.wxiaoqi.security.common.vo.PageDataVO;
import com.google.common.collect.Lists;
import com.xxfc.platform.activity.entity.Coupon;
import com.xxfc.platform.activity.feign.ActivityFeign;
import com.xxfc.platform.order.biz.inner.OrderCalculateBiz;
import com.xxfc.platform.order.biz.inner.OrderMsgBiz;
import com.xxfc.platform.order.contant.enumerate.*;
import com.xxfc.platform.order.entity.*;
import com.xxfc.platform.order.mapper.BaseOrderMapper;
import com.xxfc.platform.order.pojo.Achievement;
import com.xxfc.platform.order.pojo.DedDetailDTO;
import com.xxfc.platform.order.pojo.QueryCriteria;
import com.xxfc.platform.order.pojo.account.OrderAccountDetail;
import com.xxfc.platform.order.pojo.calculate.InProgressVO;
import com.xxfc.platform.order.pojo.dto.MemberOrderBo;
import com.xxfc.platform.order.pojo.dto.MemberOrderFindDTO;
import com.xxfc.platform.order.pojo.dto.OrderDTO;
import com.xxfc.platform.order.pojo.mq.OrderMQDTO;
import com.xxfc.platform.order.pojo.order.OrderListVo;
import com.xxfc.platform.order.pojo.order.OrderPageVO;
import com.xxfc.platform.order.pojo.order.OrderVehicleCrosstownDto;
import com.xxfc.platform.order.pojo.order.QueryOrderDTO;
import com.xxfc.platform.tour.entity.TourUser;
import com.xxfc.platform.tour.feign.TourFeign;
import com.xxfc.platform.universal.constant.DictionaryKey;
import com.xxfc.platform.universal.dto.SendMsgDTO;
import com.xxfc.platform.universal.entity.Dictionary;
import com.xxfc.platform.universal.feign.MQSenderFeign;
import com.xxfc.platform.universal.feign.ThirdFeign;
import com.xxfc.platform.vehicle.common.RestResponse;
import com.xxfc.platform.vehicle.constant.ResCode.ResCode;
import com.xxfc.platform.vehicle.entity.BookRecordUpdateLog;
import com.xxfc.platform.vehicle.entity.BranchCompany;
import com.xxfc.platform.vehicle.entity.Vehicle;
import com.xxfc.platform.vehicle.entity.VehicleUserLicense;
import com.xxfc.platform.vehicle.feign.VehicleFeign;
import com.xxfc.platform.vehicle.pojo.CompanyDetail;
import com.xxfc.platform.vehicle.util.DistanceUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
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 java.util.stream.Collectors;

import static com.github.wxiaoqi.security.common.config.rabbit.RabbitConstant.*;
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.APP_ORDER;
import static com.xxfc.platform.universal.constant.DictionaryKey.ILLEGAL_TYPE;

/**
 * @author zjw
 * @email nishijjo@qq.com
 * @date 2019-05-15 21:30:33
 */
@Service
@Slf4j
public class BaseOrderBiz extends BaseBiz<BaseOrderMapper, BaseOrder> implements UserRestInterface {

	@Autowired
	OrderMemberDetailBiz orderMemberDetailBiz;

	@Autowired
	OrderTourDetailBiz orderTourDetailBiz;

	@Autowired
	OrderRentVehicleBiz orderRentVehicleBiz;

	@Autowired
	OrderVehicleCrosstownBiz orderVehicleCrosstownBiz;

	@Autowired
	OrderUserLicenseBiz orderUserLicenseBiz;

	@Autowired
	OrderItemBiz orderItemBiz;

	@Autowired
	OrderAccountBiz orderAccountBiz;

	@Autowired
	VehicleFeign vehicleFeign;

	@Autowired
	ThirdFeign thirdFeign;

	@Autowired
	TourFeign tourFeign;

	@Autowired
	UserFeign userFeign;

	@Autowired
	MQSenderFeign mqSenderFeign;

	@Autowired
	OrderMsgBiz orderMsgBiz;

	@Autowired
	ActivityFeign activityFeign;

	@Autowired
	OrderCalculateBiz orderCalculateBiz;

	public static final DateTimeFormatter DEFAULT_DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");


	public List<OrderPageVO> pageByParm(Map<String, Object> paramMap) {
		return mapper.pageByParm(paramMap);
	}

	public List<OrderListVo> listOrder(Map<String, Object> paramMap) {
		List<OrderListVo> orderListVos = mapper.listOrder(paramMap);
		return orderListVos;
	}

	public List<OrderPageVO> getRentVehicle(Map<String, Object> paramMap) {
		return mapper.getRentVehicle(paramMap);
	}

	public List<OrderPageVO> getTourList(Map<String, Object> paramMap) {
		return mapper.getTourList(paramMap);
	}


	public PageDataVO<MemberOrderBo> findMemberOrderPage(MemberOrderFindDTO memberOrderFindDTO) {
		return PageDataVO.pageInfo(memberOrderFindDTO.getPage(), memberOrderFindDTO.getLimit(), () -> mapper.findMemberOrders(memberOrderFindDTO));
	}

	public List<MemberOrderBo> findMemberOrders(MemberOrderFindDTO memberOrderFindDTO) {
		return mapper.findMemberOrders(memberOrderFindDTO);
	}

	// public List<MemberOrderBo>

	/**
	 * 获取订单详情
	 *
	 * @param no
	 * @return
	 */
	public ObjectRestResponse<OrderPageVO> getOrderDetail(String no, UserDTO userDTO) {
		OrderPageVO orderPageVo = mapper.getOrderDetail(no);
		if (orderPageVo == null) {
			return ObjectRestResponse.createFailedResult(ResCode.ORDER_IS_NOT_EXIST.getCode(), ResCode.ORDER_IS_NOT_EXIST.getDesc());
		}
		if (orderPageVo.getStatus() <= 3 && orderPageVo.getStatus() != 2 && orderPageVo.getStatus() != -1) {
			return ObjectRestResponse.createFailedResult(ResCode.ORDER_DETAIL_IS_NOT_EXIST.getCode(), ResCode.ORDER_DETAIL_IS_NOT_EXIST.getDesc());
		}
		AppUserDTO appUserVo = userFeign.userDetailById(orderPageVo.getUserId()).getData();
		if (appUserVo != null) {
			orderPageVo.setTelephone(appUserVo.getUsername());
			orderPageVo.setUsername(appUserVo.getRealname());
		}
		List<BranchCompany> branchCompanies = vehicleFeign.companyAll(userDTO.getDataAll(), userDTO.getDataCompany(), userDTO.getDataZone());
		List<Integer> companyIds = branchCompanies.stream().map(BranchCompany::getId).collect(Collectors.toList());

		if (orderPageVo.getOrderRentVehicleDetail() != null) {

			if (!companyIds.contains(orderPageVo.getOrderRentVehicleDetail().getStartCompanyId()) && !companyIds.contains(orderPageVo.getOrderRentVehicleDetail().getEndCompanyId())) {
				return ObjectRestResponse.createFailedResult(ResCode.YOU_AUTH_FAIL.getCode(), ResCode.YOU_AUTH_FAIL.getDesc());
			}
			if (userDTO.getCompanyId() == orderPageVo.getOrderRentVehicleDetail().getEndCompanyId()) {
				orderPageVo.setUserCompanyStatus(true);
			}
			if (orderPageVo.getStatus() == 4) { //未交车
//                boolean flag = getTodayTime(orderPageVo.getOrderRentVehicleDetail().getStartTime());
//                if (!flag) {
//                    return ObjectRestResponse.createFailedResult(3501, "今日不是交车日期");
//                }
				getDriverInfo(orderPageVo);
			} else if (orderPageVo.getStatus() >= 5 || orderPageVo.getStatus() == -1) {//出行中 已交车
				//设置违约金金额
				getDriverInfo(orderPageVo);
				getUserLicense(orderPageVo);
			}
			ObjectRestResponse<CompanyDetail> startResponse = vehicleFeign.getCompanyDetail(orderPageVo.getOrderRentVehicleDetail().getStartCompanyId());
			if (startResponse.getData() != null) {
				orderPageVo.setStartCompanyName(startResponse.getData().getName());
			}

			ObjectRestResponse<CompanyDetail> restResponse = vehicleFeign.getCompanyDetail(orderPageVo.getOrderRentVehicleDetail().getEndCompanyId());
			if (restResponse.getData() != null) {
				orderPageVo.setEndCompanyName(restResponse.getData().getName());
			}
			RestResponse<Vehicle> response = vehicleFeign.findById(orderPageVo.getOrderRentVehicleDetail().getVehicleId());
			if (response.getData() != null) {
				orderPageVo.setVehicalNumberPlat(response.getData().getNumberPlate());
				orderPageVo.setCode(response.getData().getCode());
			}

		} else if (orderPageVo.getOrderTourDetail() != null) {
			if (StringUtils.isNotBlank(orderPageVo.getOrderTourDetail().getTourUserIds())) {
				List<TourUser> list = tourFeign.getTourUsers(orderPageVo.getOrderTourDetail().getTourUserIds()).getData();
				orderPageVo.getOrderTourDetail().setUserVoList(list == null || list.size() <= 0 ? new ArrayList<>() : list);
			}
		}

		//设置保留金
		Map<String, Dictionary> dictionaryMap = thirdFeign.dictionaryGetAll4Map().getData();
		BigDecimal illegalReserve = new BigDecimal(dictionaryMap.get(APP_ORDER + "_" + DictionaryKey.ILLEGAL_RESERVE).getDetail());
		orderPageVo.setIllegalReserve(illegalReserve);
		orderPageVo.setItems(orderItemBiz.selectList(new OrderItem() {{
			setOrderId(orderPageVo.getId());
		}}));
		return ObjectRestResponse.succ(orderPageVo);
	}


	/**
	 * 后台获取订单详情
	 *
	 * @param no
	 * @param userDTO
	 * @return
	 */
	public ObjectRestResponse<OrderPageVO> orderDetail(String no, UserDTO userDTO) {
		OrderPageVO orderPageVo = mapper.getOrderDetail(no);
		if (orderPageVo == null) {
			return ObjectRestResponse.createFailedResult(ResCode.ORDER_IS_NOT_EXIST.getCode(), ResCode.ORDER_IS_NOT_EXIST.getDesc());
		}
		AppUserDTO appUserVo = userFeign.userDetailById(orderPageVo.getUserId()).getData();
		if (appUserVo != null) {
			orderPageVo.setTelephone(appUserVo.getUsername());
			orderPageVo.setUsername(appUserVo.getRealname());
			orderPageVo.setPositionName(appUserVo.getPositionName());
		}
		List<BranchCompany> branchCompanies = vehicleFeign.companyAll(userDTO.getDataAll(), userDTO.getDataCompany(), userDTO.getDataZone());
		List<Integer> companyIds = branchCompanies.stream().map(BranchCompany::getId).collect(Collectors.toList());

		if (orderPageVo.getOrderRentVehicleDetail() != null) {

			if (!companyIds.contains(orderPageVo.getOrderRentVehicleDetail().getStartCompanyId()) && !companyIds.contains(orderPageVo.getOrderRentVehicleDetail().getEndCompanyId())) {
				return ObjectRestResponse.createFailedResult(ResCode.YOU_AUTH_FAIL.getCode(), ResCode.YOU_AUTH_FAIL.getDesc());
			}
			if (userDTO.getCompanyId() == orderPageVo.getOrderRentVehicleDetail().getEndCompanyId()) {
				orderPageVo.setUserCompanyStatus(true);
			}
			if (orderPageVo.getStatus() == 4) { //未交车
//                boolean flag = getTodayTime(orderPageVo.getOrderRentVehicleDetail().getStartTime());
//                if (!flag) {
//                    return ObjectRestResponse.createFailedResult(3501, "今日不是交车日期");
//                }
				getDriverInfo(orderPageVo);
			} else if (orderPageVo.getStatus() >= 5 || orderPageVo.getStatus() == -1) {//出行中 已交车
				//设置违约金金额
				getDriverInfo(orderPageVo);
				getUserLicense1(orderPageVo);
			}
			ObjectRestResponse<CompanyDetail> startResponse = vehicleFeign.getCompanyDetail(orderPageVo.getOrderRentVehicleDetail().getStartCompanyId());
			if (startResponse.getData() != null) {
				orderPageVo.setStartCompanyName(startResponse.getData().getName());
			}

			ObjectRestResponse<CompanyDetail> restResponse = vehicleFeign.getCompanyDetail(orderPageVo.getOrderRentVehicleDetail().getEndCompanyId());
			if (restResponse.getData() != null) {
				orderPageVo.setEndCompanyName(restResponse.getData().getName());
			}
			RestResponse<Vehicle> response = vehicleFeign.findById(orderPageVo.getOrderRentVehicleDetail().getVehicleId());
			if (response.getData() != null) {
				orderPageVo.setVehicalNumberPlat(response.getData().getNumberPlate());
				orderPageVo.setCode(response.getData().getCode());
			}

		} else if (orderPageVo.getOrderTourDetail() != null) {
			if (StringUtils.isNotBlank(orderPageVo.getOrderTourDetail().getTourUserIds())) {
				List<TourUser> list = tourFeign.getTourUsers(orderPageVo.getOrderTourDetail().getTourUserIds()).getData();
				orderPageVo.getOrderTourDetail().setUserVoList(list == null || list.size() <= 0 ? new ArrayList<>() : list);
			}
		}

		//设置保留金
		Map<String, Dictionary> dictionaryMap = thirdFeign.dictionaryGetAll4Map().getData();
		BigDecimal illegalReserve = new BigDecimal(dictionaryMap.get(APP_ORDER + "_" + DictionaryKey.ILLEGAL_RESERVE).getDetail());
		orderPageVo.setIllegalReserve(illegalReserve);
		orderPageVo.setItems(orderItemBiz.selectList(new OrderItem() {{
			setOrderId(orderPageVo.getId());
			setType(104);
		}}));
		return ObjectRestResponse.succ(orderPageVo);
	}


	//获取两个日期之间的天数（不包含头尾）
	public int getDaysBetweenDateTime(DateTime startDay, DateTime endDay) {
		int a = 0;
		for (DateTime curDate = startDay.plusDays(1); curDate.compareTo(endDay) < 0; curDate = curDate.plusDays(1)) {
			a++;
		}
		return a;
	}

	//获取两个日期之间的天数（包含头尾）
	public int getDaysBetweenDateTimeHasStartEnd(DateTime startDay, DateTime endDay) {
		int a = 0;
		for (DateTime curDate = startDay; curDate.compareTo(endDay) <= 0; curDate = curDate.plusHours(1)) {
			a++;
		}
		return a;
	}

//    public static void main(String[] args) {
//        DateTime dateTime = DateTime.parse("2019-09-20 12:00:00", DEFAULT_DATE_TIME_FORMATTER);
//        DateTime dateTime1 = DateTime.parse("2019-09-22 12:00:00", DEFAULT_DATE_TIME_FORMATTER);
//        BaseOrderBiz baseOrderBiz = new BaseOrderBiz();
//        OrderCalculateBiz orderCalculateBiz = new OrderCalculateBiz();
//        int a = orderCalculateBiz.getIncludeDays(1572246524350l,1572332924000l);
//        System.out.println(a);
//    }

	public void updateCrossRefund(OrderPageVO orderPageVO) {
		//计算延期费用
		DedDetailDTO dedDetailDTO = new DedDetailDTO();
		//提前还车,结束时间大于当前时间
		Long nowTime = System.currentTimeMillis();
		Long endTime = orderPageVO.getOrderRentVehicleDetail().getEndTime();
		Long startTime = orderPageVO.getOrderRentVehicleDetail().getStartTime();

		//设置使用天数
		int userUsedDay = orderCalculateBiz.getIncludeDays(startTime, nowTime);
		orderPageVO.getOrderRentVehicleDetail().setUsedDay(userUsedDay);
		orderRentVehicleBiz.updateSelectiveById(orderPageVO.getOrderRentVehicleDetail());
		//实际预定的天数
		int actualDay = orderCalculateBiz.getIncludeDays(startTime, endTime);
		InProgressVO inProgressVO = orderCalculateBiz.inProgressCalculate(orderPageVO, userUsedDay);
        JSONArray jsonArray = new JSONArray();
        if (inProgressVO != null) {
                //新增延长还车，不计免赔额,金额大于0才显示
           if (inProgressVO.getDelayAddPriceVO().getDelayDamageSafeAmount() != null && inProgressVO.getDelayAddPriceVO().getDelayDamageSafeAmount().doubleValue() > 0) {
              StringBuilder stringBuilder = new StringBuilder();
              stringBuilder.append("延长用车");
              stringBuilder.append(inProgressVO.getDelayAddPriceVO().getDelayAddDays());
              stringBuilder.append("天,  补扣不计免赔费用");
              stringBuilder.append(inProgressVO.getDelayAddPriceVO().getDelayDamageSafeAmount());
              stringBuilder.append("元");
              initDedDetail(dedDetailDTO, OrderViolateEnum.DELAY_VEHICLE.getCode(), inProgressVO.getDelayAddPriceVO().getDelayDamageSafeAmount(), stringBuilder);
              jsonArray.add(dedDetailDTO);
              orderPageVO.setDelayVehicleDetail(jsonArray.toJSONString());
              jsonArray = new JSONArray();
              dedDetailDTO = new DedDetailDTO();
           } else {
			   orderPageVO.setDelayVehicleDetail(jsonArray.toJSONString());
		   }
			/**
			 * 提前还车
			 */
			if (userUsedDay - actualDay < 0) {
				StringBuilder stringBuilder = new StringBuilder();
				//提前的天数, 当天就算使用一天
				int noUsedDay = actualDay - userUsedDay;
				//退还未使用的天数，或者金额，扣除违约金，实际未使用天数的金额，最多3000元
				//消费超额金
				if (inProgressVO.getExtraAmount() != null) {
					dedDetailDTO.setExcessCost(inProgressVO.getExtraAmount());
				}
				stringBuilder.append("违约金( ");
				stringBuilder.append(noUsedDay);
				stringBuilder.append("天) = ");
				stringBuilder.append(inProgressVO.getViolateAmount());
				initDedDetail(dedDetailDTO, OrderViolateEnum.BEFORE.getCode(), inProgressVO.getViolateAmount(), stringBuilder);
				/**
				 * 延期还车
				 */
			} else if (userUsedDay - actualDay > 0) {
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.append("违约金( ");
				//延期的天数, 延期违约金是延期天数*200%
				int extraUsedDay = userUsedDay - actualDay;
				if (extraUsedDay > 0) {
					stringBuilder.append(extraUsedDay);
					stringBuilder.append("(天)");
					stringBuilder.append(" x 2)");
					stringBuilder.append(" = ");
					stringBuilder.append(inProgressVO.getViolateAmount());
					stringBuilder.append("元");
					initDedDetail(dedDetailDTO, OrderViolateEnum.AFTER.getCode(), inProgressVO.getViolateAmount(), stringBuilder);
				}
			}
		}
		if ((dedDetailDTO.getCost() != null && dedDetailDTO.getCost().doubleValue() != 0) || (dedDetailDTO.getExcessCost() != null && dedDetailDTO.getExcessCost().doubleValue() != 0)) {
			jsonArray.add(dedDetailDTO);
		}
		DedDetailDTO dedDetailDTO1 = new DedDetailDTO();
		//添加更改还车公司计算费用
		if (orderPageVO.getOrderRentVehicleDetail() != null && orderPageVO.getOrderRentVehicleDetail().getBookRecordId() != null) {
			//查询是否有更换还车记录
			List<BookRecordUpdateLog> bookRecordUpdateLogs = vehicleFeign.get(orderPageVO.getOrderRentVehicleDetail().getBookRecordId()).getData();
			if (bookRecordUpdateLogs != null && bookRecordUpdateLogs.size() > 0) {
				orderPageVO.setBookRecordUpdateLogs(bookRecordUpdateLogs);
				//有更换记录，则需要计算更换费用
				//原始公司经纬度，列表中最后一个 bookRecordUpdateLogs.get(bookRecordUpdateLogs.size -1 ) 最后还车公司是列表中的第一条中的getNewRetCompanyId
				BookRecordUpdateLog oldCompany = bookRecordUpdateLogs.get(bookRecordUpdateLogs.size() - 1);
				BookRecordUpdateLog newCompany = bookRecordUpdateLogs.get(0);
				if (oldCompany != null && newCompany != null) {
					CompanyDetail oldCompanyDetail = vehicleFeign.getCompanyDetail(oldCompany.getOldRetCompanyId()).getData();
					CompanyDetail newCompanyDetail = vehicleFeign.getCompanyDetail(newCompany.getNewRetCompanyId()).getData();
					if (oldCompanyDetail.getLatitude() != null && oldCompanyDetail.getLongitude() != null && newCompanyDetail.getLongitude() != null && newCompanyDetail.getLatitude() != null) {
						//根据经纬度获取两个公司的距离
						double distance = DistanceUtil.getDistance(oldCompanyDetail.getLongitude().doubleValue(), oldCompanyDetail.getLatitude().doubleValue(), newCompanyDetail.getLongitude().doubleValue(), newCompanyDetail.getLatitude().doubleValue());
						log.info("两个公司的距离为(米)： {}", distance);
						BigDecimal distanceNum = new BigDecimal(distance + "").divide(new BigDecimal("1000"), 0, BigDecimal.ROUND_UP);
						//取出费用计算的单价
						Map<String, Dictionary> dictionaryMap = thirdFeign.dictionaryGetAll4Map().getData();
						BigDecimal illegalReserve = new BigDecimal(dictionaryMap.get(ILLEGAL_TYPE + "_" + DictionaryKey.ILLEGAL_FEE_PRICE).getDetail());
						BigDecimal totalCost = distanceNum.multiply(illegalReserve);
						log.info("更换两个公司的总费用为： {}", totalCost);
						StringBuilder stringBuilder = new StringBuilder();
						stringBuilder.append(illegalReserve);
						stringBuilder.append(" x ");
						stringBuilder.append(distanceNum);
						stringBuilder.append("(KM)");
						stringBuilder.append(" = ");
						stringBuilder.append(totalCost);
						stringBuilder.append("元");
						dedDetailDTO1.setCost(totalCost);
						initDedDetail(dedDetailDTO1, OrderViolateEnum.CHANGE.getCode(), totalCost, stringBuilder);
					}
				}
			}
		}
		if (dedDetailDTO1.getCost() != null && dedDetailDTO1.getCost().doubleValue() != 0) {
			jsonArray.add(dedDetailDTO1);
		}
		orderPageVO.setDedDetailDTO(jsonArray.toJSONString());
	}


	/**
	 * 初始化违约金实体
	 *
	 * @param dedDetailDTO
	 * @param type
	 * @param cost
	 * @param stringBuilder
	 */
	public void initDedDetail(DedDetailDTO dedDetailDTO, Integer type, BigDecimal cost, StringBuilder stringBuilder) {
		String detailName = null;
		if (type == OrderViolateEnum.BEFORE.getCode()) {
			dedDetailDTO.setType(OrderViolateEnum.BEFORE.getCode());
			detailName = "提前还车违约金";
		} else if (type == OrderViolateEnum.AFTER.getCode()) {
			dedDetailDTO.setType(OrderViolateEnum.AFTER.getCode());
			detailName = "延期还车违约金";
		} else if (type == OrderViolateEnum.CHANGE.getCode()) {
			dedDetailDTO.setType(OrderViolateEnum.CHANGE.getCode());
			detailName = "更换还车公司";
		} else if (type == OrderViolateEnum.DELAY_VEHICLE.getCode()) {
            dedDetailDTO.setType(OrderViolateEnum.DELAY_VEHICLE.getCode());
            detailName = "延长还车";
        }
		//900元+违约金（￥900x2天=）1800元
		dedDetailDTO.setDeductions(stringBuilder.toString());
		dedDetailDTO.setCost(cost);
		dedDetailDTO.setId(1);
		dedDetailDTO.setStatusIndex(1);
		dedDetailDTO.setStatusName(detailName);
	}

	/**
	 * 获取驾驶人驾照
	 *
	 * @param orderPageVo
	 */
	public void getUserLicense(OrderPageVO orderPageVo) {
		OrderVehicleCrosstownDto orderVehicleCrosstownDto = new OrderVehicleCrosstownDto();
		orderVehicleCrosstownDto.setOrderId(orderPageVo.getId());
		orderVehicleCrosstownDto.setOrderNo(orderPageVo.getNo());
		List<OrderVehicleCrosstownDto> orderVehicleCrosstown = orderVehicleCrosstownBiz.selectByOrderId(orderVehicleCrosstownDto);
		if (orderVehicleCrosstown != null && orderVehicleCrosstown.size() > 0) {
			List<OrderUserLicense> orderUserLicenses = orderUserLicenseBiz.selectByIds(orderVehicleCrosstown.get(0).getUserLicenseId()).getData();
			if (orderUserLicenses != null && orderUserLicenses.size() > 0) {
				orderVehicleCrosstownDto.setLicenseIdCard(orderUserLicenses.get(0).getLicenseIdCard());
				orderVehicleCrosstownDto.setLicenseImg(orderUserLicenses.get(0).getLicenseImg());
				orderVehicleCrosstownDto.setLicenseName(orderUserLicenses.get(0).getLicenseName());
				orderVehicleCrosstownDto.setLicensePhone(orderUserLicenses.get(0).getLicensePhone());
			}
			//设置违约明细
			for (OrderVehicleCrosstownDto a : orderVehicleCrosstown) {
				if (a.getType() != CrosstownTypeEnum.DEPARTURE.getCode()) {
					if (StringUtils.isNotBlank(a.getViolateDetail())) {
						orderPageVo.setDedDetailDTO(a.getViolateDetail());
					}
					if (StringUtils.isNotBlank(a.getDelayVehicleDetail())) {
						orderPageVo.setDelayVehicleDetail(a.getDelayVehicleDetail());
					}
				}
			}
		}
		if (StringUtils.isBlank(orderPageVo.getDedDetailDTO()) || StringUtils.isBlank(orderPageVo.getDelayVehicleDetail())) {
			updateCrossRefund(orderPageVo);
		}
		orderPageVo.setOrderVehicleCrosstownDto(orderVehicleCrosstownDto);
	}

	//后台获取用户驾驶信息
	public void getUserLicense1(OrderPageVO orderPageVo) {
		OrderVehicleCrosstownDto orderVehicleCrosstownDto = new OrderVehicleCrosstownDto();
		orderVehicleCrosstownDto.setOrderId(orderPageVo.getId());
		orderVehicleCrosstownDto.setOrderNo(orderPageVo.getNo());
		List<OrderVehicleCrosstownDto> orderVehicleCrosstown = orderVehicleCrosstownBiz.selectByOrderId(orderVehicleCrosstownDto);
		if (orderVehicleCrosstown != null && orderVehicleCrosstown.size() > 0) {
			List<OrderUserLicense> orderUserLicenses = orderUserLicenseBiz.selectByIds(orderVehicleCrosstown.get(0).getUserLicenseId()).getData();
			if (orderUserLicenses != null && orderUserLicenses.size() > 0) {
				orderVehicleCrosstownDto.setLicenseIdCard(orderUserLicenses.get(0).getLicenseIdCard());
				orderVehicleCrosstownDto.setLicenseImg(orderUserLicenses.get(0).getLicenseImg());
				orderVehicleCrosstownDto.setLicenseName(orderUserLicenses.get(0).getLicenseName());
				orderVehicleCrosstownDto.setLicensePhone(orderUserLicenses.get(0).getLicensePhone());
			}
			//设置违约明细
			for (OrderVehicleCrosstownDto a : orderVehicleCrosstown) {
				if (a.getType() != CrosstownTypeEnum.DEPARTURE.getCode()) {
					if (StringUtils.isNotBlank(a.getViolateDetail())) {
						orderPageVo.setDedDetailDTO(a.getViolateDetail());
					}
				}
			}
		}
		orderPageVo.setOrderVehicleCrosstownDto(orderVehicleCrosstownDto);
	}

	/**
	 * 获取驾驶人信息
	 *
	 * @param orderPageVo
	 */
	public void getDriverInfo(OrderPageVO orderPageVo) {
		List<VehicleUserLicense> vehicleUserLicenses = Lists.newArrayList();
		String myDriverIds = orderPageVo.getOrderRentVehicleDetail().getMyDriverIds();
		if (StringUtils.isNotBlank(myDriverIds)) {
			if (myDriverIds.contains(",")) {
				String[] ids = myDriverIds.split(",");
				try {
					//目前暂定一个驾驶人，后期需要更改再此更改
					RestResponse<VehicleUserLicense> restResponse = vehicleFeign.getOne(Integer.parseInt(ids[0]));
					log.info(restResponse.getMessage());
					if (restResponse.getData() != null) {
						vehicleUserLicenses.add(restResponse.getData());
					}
				} catch (Exception e) {
					log.error(e.getMessage(), e);
				}
			} else {
				try {
					vehicleUserLicenses.add(vehicleFeign.getOne(Integer.parseInt(myDriverIds.trim())).getData());
				} catch (Exception e) {
					log.error(e.getMessage(), e);
				}
			}
		}
		orderPageVo.setVehicleUserLicenses(vehicleUserLicenses);
	}

	/**
	 * 修改订单还车公司
	 *
	 * @param orderRentVehicleDetail
	 * @return
	 */
	public ObjectRestResponse save(OrderRentVehicleDetail orderRentVehicleDetail) {
		if (orderRentVehicleDetail == null || orderRentVehicleDetail.getId() == null) {
			return ObjectRestResponse.paramIsEmpty();
		}
		log.info("更新订单还车地点》》》 orderRentVehicleDetail = {}", orderRentVehicleDetail.toString());
		UserDTO userDTO = getAdminUserInfo();
		if (userDTO == null) {
			return ObjectRestResponse.createFailedResult(ResultCode.RSTOKEN_EXPIRED_CODE, ResultCode.getMsg(ResultCode.RSTOKEN_EXPIRED_CODE));
		}

		StringBuilder stringBuilder = new StringBuilder();
		OrderRentVehicleDetail oldValue = orderRentVehicleBiz.selectById(orderRentVehicleDetail.getId());
		if (oldValue == null) {
			return ObjectRestResponse.createFailedResult(ResCode.ORDER_IS_NOT_EXIST.getCode(), ResCode.ORDER_IS_NOT_EXIST.getDesc());
		}
		stringBuilder.append("修改订单和预定记录还车公司成功, 订单ID:");
		stringBuilder.append(oldValue.getOrderId());
		stringBuilder.append("; 原还车公司ID: ");
		stringBuilder.append(oldValue.getEndCompanyId());
		stringBuilder.append("; 更新后还车公司ID: ");
		stringBuilder.append(orderRentVehicleDetail.getEndCompanyId());
		stringBuilder.append("; 操作人ID：");
		stringBuilder.append(userDTO.getId());
		stringBuilder.append("; 操作人账号：");
		stringBuilder.append(userDTO.getUsername());
		//添加修改记录实体
		BookRecordUpdateLog bookRecordUpdateLog = new BookRecordUpdateLog();
		bookRecordUpdateLog.setBookRecordId(oldValue.getBookRecordId());
		bookRecordUpdateLog.setOldRetCompanyId(oldValue.getEndCompanyId());
		bookRecordUpdateLog.setNewRetCompanyId(orderRentVehicleDetail.getEndCompanyId());
		bookRecordUpdateLog.setOperaterId(userDTO.getId());
		bookRecordUpdateLog.setOperaterName(userDTO.getName());
		bookRecordUpdateLog.setOrderId(oldValue.getOrderId());
		bookRecordUpdateLog.setCreateTime(new Date());
		BeanUtil.copyProperties(orderRentVehicleDetail, oldValue, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
		CompanyDetail companyDetail = vehicleFeign.getCompanyDetail(orderRentVehicleDetail.getEndCompanyId()).getData();
		if (companyDetail != null) {
			oldValue.setEndCity(companyDetail.getAddrCity());
			oldValue.setEndAddr(companyDetail.detailAddr());
		}
		oldValue.setEndCompanyId(orderRentVehicleDetail.getEndCompanyId());
		orderRentVehicleBiz.updateSelectiveByIdRe(oldValue);
		ObjectRestResponse objectRestResponse = vehicleFeign.update(bookRecordUpdateLog);
		if (objectRestResponse != null && objectRestResponse.getRel()) {
			log.info(stringBuilder.toString());
			return ObjectRestResponse.succ();
		}
		return ObjectRestResponse.createFailedResult(1355, "修改失败！");
	}


	/**
	 * 获取订单详情，包含驾驶人信息，违约金等信息
	 *
	 * @param no
	 * @return
	 */
	public ObjectRestResponse<OrderPageVO> getOrderDetail(String no) {
		OrderPageVO orderPageVo = mapper.getOrderDetail(no);
		if (orderPageVo == null) {
			return ObjectRestResponse.createFailedResult(ResCode.ORDER_IS_NOT_EXIST.getCode(), ResCode.ORDER_IS_NOT_EXIST.getDesc());
		}
		if (orderPageVo.getOrderRentVehicleDetail() != null) {
			if (orderPageVo.getStatus() == 4) { //未交车
//                boolean flag = getTodayTime(orderPageVo.getOrderRentVehicleDetail().getStartTime());
//                if (!flag) {
//                    return ObjectRestResponse.createFailedResult(3501, "今日不是交车日期");
//                }
				getDriverInfo(orderPageVo);
			} else if (orderPageVo.getStatus() >= 5 || orderPageVo.getStatus() == -1) {//出行中 已交车
				getDriverInfo(orderPageVo);
				getUserLicense(orderPageVo);
			}
			RestResponse<Vehicle> restResponse = vehicleFeign.findById(orderPageVo.getOrderRentVehicleDetail().getVehicleId());
			if (restResponse.getData() != null) {
				orderPageVo.setVehicalNumberPlat(restResponse.getData().getNumberPlate());
			}
		} else if (orderPageVo.getOrderTourDetail() != null) {
			if (StringUtils.isNotBlank(orderPageVo.getOrderTourDetail().getTourUserIds())) {
				List<TourUser> list = tourFeign.getTourUsers(orderPageVo.getOrderTourDetail().getTourUserIds()).getData();
				orderPageVo.getOrderTourDetail().setUserVoList(list == null || list.size() <= 0 ? new ArrayList<>() : list);
			}
		}
		//设置保留金
		Map<String, Dictionary> dictionaryMap = thirdFeign.dictionaryGetAll4Map().getData();
		BigDecimal illegalReserve = new BigDecimal(dictionaryMap.get(APP_ORDER + "_" + DictionaryKey.ILLEGAL_RESERVE).getDetail());
		orderPageVo.setIllegalReserve(illegalReserve);
		orderPageVo.setItems(orderItemBiz.selectList(new OrderItem() {{
			setOrderId(orderPageVo.getId());
		}}));
		return ObjectRestResponse.succ(orderPageVo);
	}

	/**
	 * 支付回调处理
	 *
	 * @param orderNo
	 * @param tradeNo
	 */
	@Transactional
	public void payNotifyHandle(String orderNo, String tradeNo, Integer type, Integer payWay) {
		OrderRentVehicleDetail orvd = new OrderRentVehicleDetail();
		OrderTourDetail otd = new OrderTourDetail();
		OrderMemberDetail omd = new OrderMemberDetail();
		BaseOrder baseOrder = this.selectOne(new BaseOrder() {{
			setNo(orderNo);
		}});

		if (OrderStatusEnum.ORDER_UNPAY.getCode().equals(baseOrder.getStatus()) && baseOrder.getHasPay().equals(SYS_FALSE)) {
			BaseOrder updateOrder = new BaseOrder() {{
				setId(baseOrder.getId());
				setOutTradeNo(tradeNo);
				setHasPay(SYS_TRUE);
				setPayTime(System.currentTimeMillis());
				setPayOrigin(type);
				setPayWay(payWay);
				setVersion(baseOrder.getVersion());
			}};

			//订单账款类
			OrderAccountDetail oad = new OrderAccountDetail();
			oad.setOriginOrderAmount(baseOrder.getGoodsAmount().subtract(baseOrder.getCouponAmount()));
			//账单的的orderAmount 对应 的是商品金额
			oad.setOrderAmount(baseOrder.getGoodsAmount().subtract(baseOrder.getCouponAmount()));

			//如果是会员订单，则触发会员效益
			if (OrderTypeEnum.MEMBER.getCode().equals(baseOrder.getType())) {
				//直接设置订单完成
				updateOrder.setStatus(OrderStatusEnum.ORDER_FINISH.getCode());
				omd = orderMemberDetailBiz.selectOne(new OrderMemberDetail() {{
					setOrderId(baseOrder.getId());
				}});

				//触发会员效益
				UserMemberDTO userMemberDTO = new UserMemberDTO() {{
					setUserId(baseOrder.getUserId());
					setIsBind(ISBIND_BIND);
				}};
				userMemberDTO.setMemberLevel(omd.getMemberLevel());
				userMemberDTO.setRentFreeDays(omd.getRentFreeNum());
				userMemberDTO.setTotalNumber(omd.getRentFreeNum());
				userMemberDTO.setDiscount(omd.getRebate());

				ObjectRestResponse orr = userFeign.buyMember(userMemberDTO);
				log.info("orr.getStatus() : " + orr.getStatus());
			} else if (OrderTypeEnum.RENT_VEHICLE.getCode().equals(baseOrder.getType())) {
				updateOrder.setStatus(OrderStatusEnum.ORDER_TOSTART.getCode());
				orvd = orderRentVehicleBiz.selectOne(new OrderRentVehicleDetail() {{
					setOrderId(baseOrder.getId());
				}});

				//账款设置押金
				oad.setOriginDepositAmount(orvd.getDeposit());
				oad.setDepositAmount(orvd.getDeposit());

				//车辆预定审核通过
				RestResponse<Integer> result = vehicleFeign.rentProveVehicleBooking(orvd.getBookRecordId());

				//确认免费天数
				if (orvd.getFreeDays() > 0) {
					userFeign.memberDays(baseOrder.getUserId(), orvd.getFreeDays(), UserFeign.MEMBER_DAYS_CONFIRM);
				}

			} else if (OrderTypeEnum.TOUR.getCode().equals(baseOrder.getType())) {
				updateOrder.setStatus(OrderStatusEnum.ORDER_TOSTART.getCode());
				otd = orderTourDetailBiz.selectOne(new OrderTourDetail() {{
					setOrderId(baseOrder.getId());
				}});

				//站点总人数添加
				tourFeign.updateTourGoodPersonNum(otd.getVerificationId(), TourFeign.TOTAL_PERSON, otd.getTotalNumber());
			}

			try {
				BeanUtil.copyProperties(this.updateSelectiveByIdReT(updateOrder), baseOrder);
				//记录订单账款记录
				Integer flag = orderAccountBiz.addOrderAccount(baseOrder.getId(), "订单支付", oad.getOriginOrderAmount().add(oad.getOriginDepositAmount()), oad.getOrderAmount().add(oad.getDepositAmount()), tradeNo, AccountTypeEnum.IN_ORDER_PAY.getCode(), JSONUtil.toJsonStr(oad));
			} finally {
				AppUserDTO appUserDTO = userFeign.userDetailById(baseOrder.getUserId()).getData();

				//处理App用户提醒短信的发送
//                orderMsgBiz.handelAppUserMsg(orvd, omd, baseOrder, appUserDTO);
				orderMsgBiz.handelMsgPayNew(orvd, otd, omd, baseOrder, appUserDTO);

				//处理后台用户提醒短信的发送
//                orderMsgBiz.handelBgUserMsg4Pay(orvd, baseOrder, appUserDTO, OrderMsgBiz.RENT_PAY);
				sendOrderMq(orvd, otd, omd, baseOrder, OrderMQDTO.ORDER_PAY);
				if (OrderTypeEnum.MEMBER.getCode().equals(baseOrder.getType())) {
					sendOrderMq(orvd, otd, omd, baseOrder, OrderMQDTO.ORDER_FINISH);
					//订单完成时，payway为 支付宝，则转支付
					baseOrder.setPayWay(payWay);
					orderAccountBiz.finishFreeze2PayAmount(baseOrder);
				}
			}
		} else {
			log.error(" order has payed , orderNo:{}, tradeNo:{} ", orderNo, tradeNo);
		}
	}

	public void sendOrderMq(OrderRentVehicleDetail orvd, OrderTourDetail otd, OrderMemberDetail omd, BaseOrder baseOrder, Integer sign) {
		//发送队列消息
		OrderMQDTO orderMQDTO = BeanUtil.toBean(baseOrder, OrderMQDTO.class);
		orderMQDTO.setOrderRentVehicleDetail(orvd);
		orderMQDTO.setOrderTourDetail(otd);
		orderMQDTO.setOrderMemberDetail(omd);

		//获取item
		orderMQDTO.setItems(orderItemBiz.selectList(new OrderItem() {{
			setOrderId(baseOrder.getId());
		}}));

		sendQueue(orderMQDTO, sign);
	}

	public ObjectRestResponse updateBaseOrder(BaseOrder baseOrder) {
		if(baseOrder.getId() == null) {
			return ObjectRestResponse.paramIsEmpty();
		}
		BaseOrder oldValue = mapper.selectByPrimaryKey(baseOrder.getId());
		if (oldValue == null) {
			return ObjectRestResponse.createFailedResult(ResCode.ORDER_IS_NOT_EXIST.getCode(), ResCode.ORDER_IS_NOT_EXIST.getDesc());
		}
		BeanUtil.copyProperties(baseOrder, oldValue, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
		updateSelectiveByIdReT(oldValue);
		return ObjectRestResponse.succ();
	}


	@Override
	public void updateSelectiveById(BaseOrder entity) {
		super.updateSelectiveById(entity);
	}

	/**
	 * 更新（不成功抛异常）
	 *
	 * @param baseOrder
	 * @return
	 */
	public BaseOrder updateSelectiveByIdReT(BaseOrder baseOrder) {
		return updateSelectiveByIdReT(baseOrder, false);
	}

	/**
	 * 更新（不成功抛异常）
	 *
	 * @param baseOrder
	 * @return
	 */
	public BaseOrder updateSelectiveByIdReT(BaseOrder baseOrder, boolean needVersion) {
		if (needVersion) {
			baseOrder.setVersion(selectById(baseOrder.getId()).getVersion());
		}
		if (updateSelectiveByIdRe(baseOrder) > 0) {
			return selectById(baseOrder.getId());
		} else {
			log.error(StrUtil.format("数据更新失败：baseOrder: {}", JSONUtil.toJsonStr(baseOrder)));
			throw new BaseException(ResultCode.DB_OPERATION_FAIL_CODE);
		}
	}


//    /**
//     * 更新（不成功抛异常）
//     * @param baseOrder
//     * @return
//     */
//    public BaseOrder updateSelectiveByIdReT(BaseOrder baseOrder) {
//        if(updateSelectiveByIdRe(baseOrder) > 0) {
//            return selectById(baseOrder.getId());
//        }else {
//            throw new BaseException(ResultCode.DB_OPERATION_FAIL_CODE);
//        }
//    }

	public boolean getTodayTime(Long time) {
		Long startTime = getDayStart();
		if (time >= startTime && time <= startTime + 24 * 60 * 60 * 1000 - 1) {
			return true;
		}
		return false;
	}

	public static Long getDayStart() {
		long current = System.currentTimeMillis();
		long zero = current / (1000 * 3600 * 24) * (1000 * 3600 * 24) - TimeZone.getDefault().getRawOffset();
		return zero;
	}

	private void sendQueue(OrderMQDTO orderMQDTO, Integer sign) {
		try {
			orderMQDTO.setSign(sign);
			SendMsgDTO sendMsgDTO = new SendMsgDTO() {{
				setExchange(ORDER_TOPIC);
			}};
			sendMsgDTO.setJson(JSONUtil.toJsonStr(orderMQDTO));
			switch (sign) {
				case 2:
					sendMsgDTO.setRoutKey(KEY_ORDER_CANCEL);
					break;
				case 4:
					sendMsgDTO.setRoutKey(KEY_ORDER_PAY);
					break;
				case 6:
					sendMsgDTO.setRoutKey(KEY_ORDER_FINLISH);
					break;
				case 101:
					sendMsgDTO.setRoutKey(KEY_ORDER_PART_DEPOSIT);
					break;
				default:
					break;
			}
			mqSenderFeign.postSendMessage(sendMsgDTO);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
	}

	public Query initQuery(String no) {
		QueryOrderDetailDTO qodd = new QueryOrderDetailDTO();
		//qodd.setCrtUser(Integer.valueOf(BaseContextHandler.getUserID()));
		qodd.setUserId(Integer.valueOf(BaseContextHandler.getUserID()));
		qodd.setNo(no);
		qodd.setLimit(1);
		qodd.setPage(1);
		Query query = new Query(qodd);
		return query;
	}

	public Query initBgQuery(String no) {
		Query query = initQuery(no);
		query.put("crtUser", null);
		query.put("userId", null);
		return query;
	}

	@Override
	public UserFeign getUserFeign() {
		return userFeign;
	}

	/**
	 * 订单查询类
	 */
	@Data
	public static class QueryOrderDetailDTO extends QueryOrderDTO {
		private String no;
	}

	/**
	 * 获取退还优惠卷
	 *
	 * @param orderId
	 */
	public List<Coupon> getReturnCouponByOrderId(Integer orderId) {
		BaseOrder baseOrder = mapper.selectByPrimaryKey(orderId);
		String backCoupon = baseOrder.getBackCoupon();
		if (StringUtils.isNotBlank(backCoupon)) {
			String[] couponArray = backCoupon.split(",");
			return activityFeign.couponsByTickerNoList(Lists.newArrayList(couponArray));
		}
		return Lists.newArrayList();
	}

    public List<OrderDTO> selectOrdersByTypeAndTime(List<Integer> types, Integer hasPay, Date startDate, Date endDate) {
        List<OrderDTO>  orderDTOS = mapper.selectOrdersByTypeAndTime(types,hasPay,startDate,endDate);
        return CollectionUtils.isEmpty(orderDTOS)?Collections.EMPTY_LIST:orderDTOS;
    }

    public List<OrderDTO> selectBaeOrderByOrderIds(List<Integer> orderIds) {
          List<OrderDTO> orderDTOList = mapper.selectBaeOrderByOrderIds(orderIds);
        return CollectionUtils.isNotEmpty(orderDTOList)?Collections.EMPTY_LIST:orderDTOList;
    }

    public List<OrderPageVO> selectAllRentVehicleOrder(Map<String, Object> paramMap) {
        return mapper.selectAllRentVehicleOrder(paramMap);
    }

    public List<OrderPageVO> selectAllCountOrder(Map<String, Object> paramMap) {
        return mapper.selectAllCountOrder(paramMap);
    }


    public List<Achievement> entryStatisticalData(QueryCriteria queryCriteria) {
       return mapper.selectTotalStatistical(queryCriteria);
    }



    public PageInfo<Achievement> getAchievementPageInfo(QueryCriteria queryCriteria) {
        PageHelper.startPage(queryCriteria.getPage(),queryCriteria.getLimit());
        List<Achievement> achievements = mapper.selectTotalStatistical(queryCriteria);
        return  PageInfo.of(achievements);
    }


}