package com.prolog.rdc.tms.app.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.prolog.common.util.DateUtils;
import com.prolog.common.util.ToolKits;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.exception.PrologException;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.utils.ObjectUtils;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.rdc.tms.app.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.app.constant.SeriaNnumberConstant;
import com.prolog.rdc.tms.app.constant.enums.AppointCreateModeEnum;
import com.prolog.rdc.tms.app.constant.enums.DriverReceiveStatusEnum;
import com.prolog.rdc.tms.app.dao.mapper.*;
import com.prolog.rdc.tms.app.model.dto.*;
import com.prolog.rdc.tms.app.model.entity.*;
import com.prolog.rdc.tms.app.model.vo.*;
import com.prolog.rdc.tms.app.model.vo.business.ShipbillOperateLogSaveNewVO;
import com.prolog.rdc.tms.app.model.vo.business.ShipbillOperateLogSaveVO;
import com.prolog.rdc.tms.app.proxy.MainDataProxy;
import com.prolog.rdc.tms.app.service.PendingAppointmentService;
import com.prolog.rdc.tms.app.service.business.LoadingBillService;
import com.prolog.rdc.tms.app.service.business.PendingReceiptService;
import com.prolog.rdc.tms.app.service.business.ShipbillOperateLogService;
import com.prolog.rdc.tms.app.util.MessageUtil;
import com.prolog.rdc.tms.model.dto.basicData.TmsBaseBranchApTimeDTO;
import com.prolog.rdc.tms.model.dto.basicData.TmsBaseBranchDTO;
import com.prolog.rdc.tms.model.dto.fleetManagement.DriverCheckDTO;
import com.prolog.rdc.tms.model.dto.message.SendMessageDTO;
import com.prolog.rdc.tms.model.entity.SysParamConfigModel;
import com.prolog.rdc.tms.model.enums.MessageOrderTypeEnum;
import com.prolog.rdc.tms.model.enums.MessageTypeEnum;
import com.prolog.rdc.tms.model.vo.fleetManagement.DriverCheckVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 *
 *
 * 司机APP-待预约实现层
 *
 * @className :PendingAppointmentServiceImpl
 * @author :qian.yh
 * @creationTime :2022/07/04
 * @description :
 *
 * @modifier :
 * @modifyTime :
 * @reviseRemarks:
 *
 * @version :1.0.0
 *
 */
@Service
public class PendingAppointmentServiceImpl implements PendingAppointmentService {
	@Autowired
	private MaindataFeign maindataTmsResource;

	@Resource
	private TmsAppointmentHeaderMapper tmsAppointmentHeaderMapper;

	@Resource
	private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

	@Resource
	private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

	@Resource
	private TmsAppointmentDetailMapper tmsAppointmentDetailMapper;

	@Autowired
	private ShipbillOperateLogService shipbillOperateLogService;

	@Autowired
	private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

	@Autowired
	private MaindataFeign maindataFeign;

	@Autowired
	private LoadingBillService loadingBillService;

	@Autowired
	protected MainDataProxy mainDataProxy;

	@Autowired
	private PendingReceiptService pendingReceiptService;

	/**
	 * 仓库任务数汇总查询
	 */
	@Override
	public List<PendingAppointmentQueryDTO> pendingAppointmentQuery(PendingAppointmentQueryVO pendingAppointmentQueryVO) throws Exception {
		ToolKits.isParamNull(pendingAppointmentQueryVO, "司机待预约汇总查询请求参数不为空");
		ToolKits.isParamNull(pendingAppointmentQueryVO.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(pendingAppointmentQueryVO.getVehiclePlateNumber(), "车牌号不为空");
		ToolKits.isParamNull(pendingAppointmentQueryVO.getEnterpriseId(), "企业ID不能为空");
		List<PendingAppointmentQueryDTO> dtos = tmsShipbillHeaderMapper.pendingAppointmentQuery(pendingAppointmentQueryVO);
		if (ObjectUtils.isEmpty(dtos)) {
			throw new RuntimeException("未找到待预约的！");
		}
		return dtos;
	}

	/**
	 * 司机待预约派车单模式查询
	 * 
	 * @param pendingAppointmentQueryVO
	 * @return
	 */
	@Override
	public List<PendingAppointmentQueryDTO> pendingAppointmentQueryLoadBill(PendingAppointmentQueryVO pendingAppointmentQueryVO) {
		ToolKits.isParamNull(pendingAppointmentQueryVO, "司机待预约派车单模式查询请求参数不为空");
		ToolKits.isParamNull(pendingAppointmentQueryVO.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(pendingAppointmentQueryVO.getVehiclePlateNumber(), "车牌号不为空");
		ToolKits.isParamNull(pendingAppointmentQueryVO.getEnterpriseId(), "企业ID不能为空");
		List<PendingAppointmentQueryDTO> dtos = tmsShipbillHeaderMapper.pendingAppointmentQueryLoadBillType(pendingAppointmentQueryVO);
		if (ObjectUtils.isEmpty(dtos)) {
			throw new RuntimeException("未找到待预约的！");
		}
		return dtos;
	}

	/**
	 * 仓库预约资源查询
	 */
	@Override
	public List<PendingAppointmentDetailQueryDTO> pendingAppointmentDetailQuery(PendingAppointmentDetailQueryVO pendingAppointmentDetailQueryVO) throws Exception {
		ToolKits.isParamNull(pendingAppointmentDetailQueryVO, "司机待预约明细查询请求参数不为空");
		ToolKits.isParamNull(pendingAppointmentDetailQueryVO.getShipbillIds(), "选择的运单ID不为空");
		ToolKits.isParamNull(pendingAppointmentDetailQueryVO.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(pendingAppointmentDetailQueryVO.getEnterpriseId(), "企业ID不能为空");

		String[] shipbillIds = pendingAppointmentDetailQueryVO.getShipbillIds().split(",");
		List<TmsShipbillHeaderModel> shipbillHeaderModels = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, shipbillIds, null);
		if (ObjectUtils.isEmpty(shipbillHeaderModels)) {
			throw new RuntimeException("未找到对应的运单明细！");
		}

		List<PendingAppointmentDetailQueryDTO> returndtos = new ArrayList<PendingAppointmentDetailQueryDTO>();
		for (TmsShipbillHeaderModel headerModel : shipbillHeaderModels) {
			PendingAppointmentDetailQueryDTO dto = new PendingAppointmentDetailQueryDTO();
			dto.setShipbillId(headerModel.getShipbillId());
			dto.setEnterpriseId(pendingAppointmentDetailQueryVO.getEnterpriseId());
			dto.setDriverId(pendingAppointmentDetailQueryVO.getDriverId());
			dto.setShipbillNo(headerModel.getShipbillNo());
			dto.setOrderDate(headerModel.getOrderDate());
			dto.setShipfromId(String.valueOf(headerModel.getShipperId()));
			dto.setShipfromCode(headerModel.getShipperCode());
			dto.setShipfromName(headerModel.getShipperName());
			dto.setShipfromAddress(headerModel.getShipperAddress());
			dto.setShipfromDate(headerModel.getEstimatedPickupStartTime());
			dto.setLoadingBillId(loadingBillService.getLoadingBillIdByShipBillId(headerModel.getShipbillId()));

			dto.setShipToCode(String.valueOf(headerModel.getConsigneeId()));
			dto.setShipToName(headerModel.getConsigneeName());
			dto.setShipToAddress(headerModel.getConsigneeAddress());
			dto.setShipToConsignee(headerModel.getConsigneeContact());
			dto.setShipToConsigneeMobel(headerModel.getConsigneePhoneNumber());
			dto.setShipToConsigneeTel(headerModel.getConsigneeLandlineNumber());

			ShipbillDetailQueryVO vo = new ShipbillDetailQueryVO();
			vo.setEnterpriseId(dto.getEnterpriseId());
			vo.setShipbillId(dto.getShipbillId());
			List<ShipbillItemDetailQueryDTO> itemDetails = tmsShipbillHeaderMapper.shipbillItemDetailQuery(vo);
			dto.setItemDetail(itemDetails);
			dto.setPackageDetailDTOList(pendingReceiptService.getPackageDetailDTO(dto.getShipbillId()));
			returndtos.add(dto);
		}
		return returndtos;
	}

	/**
	 * 仓库预约资源查询
	 */
	@Override
	public WarehouseAppointmentResourceQueryDTO warehouseAppointmentResourceQuery(WarehouseAppointmentResourceQueryVO warehouseAppointmentResourceQueryVO) throws Exception {
		ToolKits.isParamNull(warehouseAppointmentResourceQueryVO, "仓库预约资源查询请求参数不为空");
		ToolKits.isParamNull(warehouseAppointmentResourceQueryVO.getBranchId(), "仓库ID不为空");
		ToolKits.isParamNull(warehouseAppointmentResourceQueryVO.getEnterpriseId(), "企业ID不能为空");

		Long branchid = Long.parseLong(warehouseAppointmentResourceQueryVO.getBranchId());
		TmsBaseBranchDTO tmsBaseBranchDTO = new TmsBaseBranchDTO();
		WarehouseAppointmentResourceQueryDTO dto = new WarehouseAppointmentResourceQueryDTO();

		RestMessage<TmsBaseBranchDTO> restMessageData = maindataTmsResource.viewBranch(branchid);
		if (!restMessageData.isSuccess()) {
			throw new RuntimeException("获取仓库的预约信息失败!");
		} else {
			tmsBaseBranchDTO = restMessageData.getData();
		}

		List<Date> aptDateList = Lists.newArrayList();
		Date nonAptSpecStartDate = tmsBaseBranchDTO.getNonAptSpecStartDate();
		Date nonAptSpecEndDate = tmsBaseBranchDTO.getNonAptSpecEndDate();

		String nonAptWeek = null;
		String nonAptMonth = null;
		if (DataDictionaryConstant.NON_ABL_DT_WK.equals(tmsBaseBranchDTO.getNonAptDt())) {
			// 不可预约日期 按周
			nonAptWeek = tmsBaseBranchDTO.getNonAptDura();
		} else if (DataDictionaryConstant.NON_ABL_DT_MT.equals(tmsBaseBranchDTO.getNonAptDt())) {
			// 不可预约日期 按月
			nonAptMonth = tmsBaseBranchDTO.getNonAptDura();
		}

		// 一周内可预约的日期
		Date currentDt = DateUtil.date();
		while (aptDateList.size() < 7) {
			if (ToolKits.isNotEmpty(nonAptSpecStartDate) && ToolKits.isNotEmpty(nonAptSpecEndDate) && DateUtil.compare(currentDt, nonAptSpecStartDate) >= 0 && DateUtil.compare(currentDt, nonAptSpecEndDate) < 0) {
				currentDt = DateUtil.offsetDay(nonAptSpecEndDate, 1);
				continue;

			}
			if (ToolKits.isNotEmpty(nonAptMonth) && nonAptMonth.contains(DateUtil.format(currentDt, "dd"))) {
				currentDt = DateUtil.offsetDay(currentDt, 1);
				continue;
			}
			if (ToolKits.isNotEmpty(nonAptWeek) && nonAptWeek.contains(String.valueOf(DateUtil.dayOfWeek(currentDt)))) {
				currentDt = DateUtil.offsetDay(currentDt, 1);
				continue;
			}
			aptDateList.add(currentDt);
			currentDt = DateUtil.offsetDay(currentDt, 1);
		}
		// 已经预约次数取得
		AppointmentHeadQueryVO queryVO = new AppointmentHeadQueryVO();
		queryVO.setBranchId(branchid);
		queryVO.setAppointmentType(DataDictionaryConstant.APPOINTMENT_TYPE_TH);
		List<BranchAppointmentInfoDTO> appointmentInfoDTOS = tmsAppointmentHeaderMapper.queryBranchAppointmentInfo(queryVO);

		Map<String, Integer> appInfoMap = Maps.newHashMap();
		for (BranchAppointmentInfoDTO infoDTO : appointmentInfoDTOS) {
			String appedDt = DateUtil.format(infoDTO.getAppointmentDate(), "yyyy-MM-dd");
			appInfoMap.put(appedDt + infoDTO.getAppointmentTime(), infoDTO.getAppointmentCnt());
		}
		// 一周的预约信息
		List<AppointmentWeekDTO> weekDTOS = Lists.newArrayList();
		// STD-DEVELOP20220823 lhb JC_CK_001仓库预约时间段可以输入分钟的需求 20220823 start
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		// STD-DEVELOP20220823 lhb JC_CK_001仓库预约时间段可以输入分钟的需求 20220823 end
		for (Date dt : aptDateList) {
			AppointmentWeekDTO weekDTO = new AppointmentWeekDTO();
			weekDTO.setAptWeek(DateUtil.dayOfWeekEnum(dt).toChinese().replace("星期", "周"));
			String aliAppDt = DateUtil.format(dt, "yyyy-MM-dd");
			weekDTO.setAptDate(aliAppDt);

			// 可预约时间段 可预约次数
			List<AppointmentTimesDTO> appointmentTimesDTOS = Lists.newArrayList();
			for (TmsBaseBranchApTimeDTO apTimeDTO : tmsBaseBranchDTO.getApTimeDTOList()) {
				// 预约时间段是否过去时间
				// STD-DEVELOP20220823 lhb JC_CK_001仓库预约时间段可以输入分钟的需求 20220823 start
				String currentDtStr = DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm");
				// STD-DEVELOP20220823 lhb JC_CK_001仓库预约时间段可以输入分钟的需求 20220823 end
				Date currentDate1 = sdf.parse(currentDtStr);
				// STD-DEVELOP20220823 lhb JC_CK_001仓库预约时间段可以输入分钟的需求 20220823 start
				Date lastDt = sdf.parse(aliAppDt + " " + apTimeDTO.getEndTime());
				// STD-DEVELOP20220823 lhb JC_CK_001仓库预约时间段可以输入分钟的需求 20220823 end
				if (lastDt.before(currentDate1)) {
					continue;
				}

				AppointmentTimesDTO timesDTO = new AppointmentTimesDTO();
				String appDura = apTimeDTO.getStartTime() + "-" + apTimeDTO.getEndTime();
				timesDTO.setAppDura(appDura);
				if (ToolKits.isNotEmpty(appointmentInfoDTOS)) {
					Integer appedCnt = appInfoMap.get(aliAppDt + appDura);
					if (ToolKits.isNotEmpty(appedCnt)) {
						int aliCnt = 0;
						if (tmsBaseBranchDTO.getAptNum().intValue() - appedCnt.intValue() > 0) {
							aliCnt = tmsBaseBranchDTO.getAptNum().intValue() - appedCnt.intValue();
						}
						timesDTO.setAppAliCnt(aliCnt);
						timesDTO.setAppedCnt(appedCnt);
					} else {
						timesDTO.setAppAliCnt(tmsBaseBranchDTO.getAptNum());
						timesDTO.setAppedCnt(0);
					}
				} else {
					timesDTO.setAppAliCnt(tmsBaseBranchDTO.getAptNum());
					timesDTO.setAppedCnt(0);
				}
				appointmentTimesDTOS.add(timesDTO);
			}
			weekDTO.setAppointmentTimes(appointmentTimesDTOS);

			weekDTOS.add(weekDTO);
		}

		dto.setBranchId(branchid);
		dto.setAppointmentWeeks(weekDTOS);
		return dto;
	}

	/**
	 * 预约确认
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public AppointmentConfirmationDTO appointmentConfirmation(AppointmentConfirmationVO appointmentConfirmationVO) throws Exception {
		ToolKits.isParamNull(appointmentConfirmationVO, "提货预约确认请求不为空");
		ToolKits.isParamNull(appointmentConfirmationVO.getShipfrom(), "仓库ID不为空");
		ToolKits.isParamNull(appointmentConfirmationVO.getAppointmentDate(), "预约日期不为空");
		ToolKits.isParamNull(appointmentConfirmationVO.getEnterpriseId(), "企业不能为空");
		ToolKits.isParamNull(appointmentConfirmationVO.getDriverId(), "司机不为空");
		ToolKits.isParamNull(appointmentConfirmationVO.getVehiclePlateNumber(), "车牌号不为空");
		ToolKits.isParamNull(appointmentConfirmationVO.getAppointTime(), "预约时间不为空");

		UserEntity user = PlgFxUsrUtils.getUserEntity();
		com.prolog.common.util.ToolKits.isParamNull(user, "当前人员没有操作权限");
		Long branchid = Long.parseLong(appointmentConfirmationVO.getShipfrom());

		String driverOpenReceiveReject = mainDataProxy.getSystemParamByCode(DataDictionaryConstant.DRIVER_OPEN_RECEIVE_REJECT);
		// 预约时间校验
		TmsBaseBranchDTO tmsBaseBranchDTO = new TmsBaseBranchDTO();
		RestMessage<TmsBaseBranchDTO> restMessageData = maindataTmsResource.viewBranch(branchid);
		if (!restMessageData.isSuccess()) {
			throw new RuntimeException("获取仓库的预约信息失败!");
		} else {
			tmsBaseBranchDTO = restMessageData.getData();
		}
		// 司机资料
		DriverCheckVO driverCheckVO = new DriverCheckVO();
		driverCheckVO.setId(Long.valueOf(appointmentConfirmationVO.getDriverId()));
		RestMessage<DriverCheckDTO> restDriverData = maindataTmsResource.getDriverExecute(driverCheckVO);
		DriverCheckDTO driverCheckDTO = new DriverCheckDTO();
		if (!restDriverData.isSuccess()) {
			throw new RuntimeException("获取仓库的预约信息失败!");
		} else {
			driverCheckDTO = restDriverData.getData();
		}

		Date date = DateUtil.date();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		SimpleDateFormat formattime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		Date appDt = formatter.parse(appointmentConfirmationVO.getAppointmentDate());
		String appTime = appointmentConfirmationVO.getAppointTime();

		Date appStartTime = formattime.parse(appointmentConfirmationVO.getAppointmentDate() + " " + appTime.substring(0, 2) + ":00:00");
		Date appEndTime = formattime.parse(appointmentConfirmationVO.getAppointmentDate() + " " + appTime.substring(6, 8) + ":00:00");

		Integer aptTimeType = tmsBaseBranchDTO.getAptTime();
		Integer aptTimeUnit = tmsBaseBranchDTO.getAptUnit();

		// 最大预约次数取得
		AppointmentHeadQueryVO queryVO = new AppointmentHeadQueryVO();
		queryVO.setBranchId(branchid);
		queryVO.setAppointmentDate(appDt);
		queryVO.setAppointmentType(DataDictionaryConstant.APPOINTMENT_TYPE_TH);
		queryVO.setAppointmentTime(appTime);
		List<BranchAppointmentInfoDTO> appointmentInfoDTOS = tmsAppointmentHeaderMapper.queryBranchAppointmentInfo(queryVO);
		if (com.prolog.common.util.ToolKits.isNotEmpty(appointmentInfoDTOS) && appointmentInfoDTOS.get(0).getAppointmentCnt().intValue() >= tmsBaseBranchDTO.getAptNum().intValue()) {
			throw new PrologException("仓库【" + branchid + "】的预约时间段" + appointmentConfirmationVO.getAppointmentDate() + appTime + "已约满");
		}
		AppointmentConfirmationDTO appointmentConfirmationDTO = new AppointmentConfirmationDTO();

		// 可预约的时间
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		Date aliAppDtStart = null;
		Date aliAppDtEnd = null;

		String appDtStr = DateUtil.format(appDt, "yyyy-MM-dd");

		Date appTimeStart = sdf.parse(appDtStr + " " + appTime.substring(0, 5));
		Date appTimeEnd = sdf.parse(appDtStr + " " + appTime.substring(6));

		Criteria criteriaTransLog = Criteria.forClass(TmsShipbillTransLogModel.class);
		Restriction r1 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, user.getEnterpriseId());
		Restriction r2 = null;
		Restriction r3 = null;
		int jiaJiCnt = 0;
		List<TmsShipbillHeaderModel> headerModelList = Lists.newArrayList();
		String[] shipBillIds = appointmentConfirmationVO.getShipbillIds().split(",");
		List<TmsShipbillHeaderModel> shipbillHeaderModels = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class,shipBillIds, null);
		if (ToolKits.isEmpty(shipbillHeaderModels)) {
			throw new PrologException(StrUtil.format("运单不存在"));
		}
		List<TmsShipbillHeaderModel> noTakeAndCallShipbillHeaderModels = shipbillHeaderModels.stream().filter(h->!h.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_APPOINTMENT_TN_CN)).collect(Collectors.toList());
		if (ToolKits.isNotEmpty(noTakeAndCallShipbillHeaderModels) && noTakeAndCallShipbillHeaderModels.size() != shipBillIds.length) {
			throw new PrologException("请勾选相同预约流程的运单");
		}
		List<TmsShipbillHeaderModel> hasTakeAndCallShipbillHeaderModels = shipbillHeaderModels.stream().filter(h->h.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_APPOINTMENT_TN_CN)).collect(Collectors.toList());
		if (ToolKits.isNotEmpty(hasTakeAndCallShipbillHeaderModels) && hasTakeAndCallShipbillHeaderModels.size() != shipBillIds.length) {
			throw new PrologException("请勾选相同预约流程的运单");
		}

		for (String shipbillId : appointmentConfirmationVO.getShipbillIds().split(",")) {
			r2 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, shipbillId);

			criteriaTransLog.setRestriction(Restrictions.and(r1, r2));
			List<TmsShipbillTransLogModel> tmsShipbillTransLogModels = tmsShipbillTransportLogMapper.findByCriteria(criteriaTransLog);

			if (ToolKits.isEmpty(tmsShipbillTransLogModels)) {
				throw new PrologException("预约时间不在仓库【" + tmsBaseBranchDTO.getName() + "】的可预约时间段内");
			} else {
				TmsShipbillTransLogModel logModel = tmsShipbillTransLogModels.get(0);
				if (DataDictionaryConstant.AVAILABLE_TIME_PICK_UP.equals(aptTimeType)) {
					aliAppDtStart = logModel.getEstimatedPickupStartTime();
				} else if (DataDictionaryConstant.AVAILABLE_TIME_ORDER.equals(aptTimeType)) {
					aliAppDtStart = logModel.getOrderDt();
				} else if (DataDictionaryConstant.AVAILABLE_TIME_COMMIT.equals(aptTimeType)) {
					aliAppDtStart = logModel.getCommitDt();
				} else if (DataDictionaryConstant.AVAILABLE_TIME_REVIEW.equals(aptTimeType)) {
					aliAppDtStart = logModel.getReviewDt();
				} else if (DataDictionaryConstant.AVAILABLE_TIME_DISPATCH.equals(aptTimeType)) {
					aliAppDtStart = logModel.getDisDt();
				} else if (DataDictionaryConstant.AVAILABLE_TIME_DISPATCH_CHECK.equals(aptTimeType)) {
					aliAppDtStart = logModel.getDisCheckDt();
				}
				if (ToolKits.isNotEmpty(aliAppDtStart)) {
					if (ToolKits.isNotEmpty(aptTimeUnit) && DataDictionaryConstant.AVAILABLE_UNIT_HOUR.equals(aptTimeUnit)) {
						aliAppDtEnd = DateUtil.offsetHour(aliAppDtStart, tmsBaseBranchDTO.getAptTimeDura().intValue());
					} else if (ToolKits.isNotEmpty(aptTimeUnit) && DataDictionaryConstant.AVAILABLE_UNIT_DAY.equals(aptTimeUnit)) {
						aliAppDtEnd = DateUtil.offsetDay(aliAppDtStart, tmsBaseBranchDTO.getAptTimeDura().intValue());
					}
					// 预约的结束时间段 < 可预约的开始时间,或者，预约的开始时间段 > 可预约的结束时间
					if (appTimeEnd.before(aliAppDtStart) || appTimeStart.after(aliAppDtEnd)) {
						throw new PrologException("预约时间不在仓库【" + tmsBaseBranchDTO.getName() + "】的可预约时间段内");
					}
				}
			}
			TmsShipbillHeaderModel headerModel = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);

			if (ToolKits.isEmpty(headerModel)) {
				throw new PrologException("运单【" + shipbillId + "】不存在");
			}
			if (DataDictionaryConstant.DRIVER_OPEN_RECEIVE_REJECT_OPEN.equals(driverOpenReceiveReject) &&
					DriverReceiveStatusEnum.N.getCode().equals(headerModel.getDriverReceiveStatus())) {
				throw new PrologException("运单【" + shipbillId + "】未接单，不能预约");
			}
			if (!headerModel.getStatus().equals(DataDictionaryConstant.SHIPBILL_STATUS_PENDING_APP)) {
				throw new PrologException("运单不是待预约状态，不能预约");
			}

			if (headerModel.getOrderType().intValue() > DataDictionaryConstant.ORDER_TYPE_P.intValue()) {
				jiaJiCnt++;
			}
			headerModelList.add(headerModel);
		}

		// 获取预约主表ID
		RestMessage<String> restMessageId = maindataTmsResource.getCodeNumberByCode(SeriaNnumberConstant.TMS_APPOINTMENT_HEADER_ID, "L");
		if (!restMessageId.isSuccess()) {
			throw new RuntimeException("生成预约主表ID失败");
		}
		String id = restMessageId.getData();

		// 预约主表作成
		TmsAppointmentHeaderModel appointmentHeaderModel = new TmsAppointmentHeaderModel();
		appointmentHeaderModel.setAppointmentId(id);
		appointmentHeaderModel.setAppointmentNo(id);
		appointmentHeaderModel.setAppointmentType(DataDictionaryConstant.APPOINTMENT_TYPE_TH);
		appointmentHeaderModel.setStatus(10);
		appointmentHeaderModel.setBranchId(tmsBaseBranchDTO.getId());
		appointmentHeaderModel.setBranchCode(tmsBaseBranchDTO.getCode());
		appointmentHeaderModel.setBranchName(tmsBaseBranchDTO.getName());
		appointmentHeaderModel.setBranchAddress(tmsBaseBranchDTO.getAddress());
		appointmentHeaderModel.setAppointmentDate(appDt);
		appointmentHeaderModel.setAppointmentTime(appTime);
		appointmentHeaderModel.setReserveNumberTime(new Date());
		appointmentHeaderModel.setShipbillQuantity(headerModelList.size());
		appointmentHeaderModel.setDriverId(Long.parseLong(appointmentConfirmationVO.getDriverId()));
		appointmentHeaderModel.setDriverCode(driverCheckDTO.getCode());
		appointmentHeaderModel.setDriverName(driverCheckDTO.getName());
		appointmentHeaderModel.setDriverPhoneNumber(driverCheckDTO.getPhoneNumber());
		appointmentHeaderModel.setVehiclePlateNumber(appointmentConfirmationVO.getVehiclePlateNumber());

		appointmentHeaderModel.setEnterpriseId(user.getEnterpriseId());
		appointmentHeaderModel.setEnterpriseName(user.getEnterpriseName());
		appointmentHeaderModel.setCreatetime(new Date());
		appointmentHeaderModel.setCreateperson(user.getNickname());
		appointmentHeaderModel.setUpdatetime(new Date());
		appointmentHeaderModel.setUpdateperson(user.getNickname());

		BigDecimal totalPcs = BigDecimal.ZERO;
		BigDecimal totalVolume = BigDecimal.ZERO;
		BigDecimal totalWeight = BigDecimal.ZERO;
		for (TmsShipbillHeaderModel detailModel : headerModelList) {
			if (detailModel.getOrderType().intValue() != DataDictionaryConstant.ORDER_TYPE_P.intValue()) {
				jiaJiCnt++;
			}
			totalPcs = totalPcs.add(detailModel.getTotalPcs());
			totalVolume = totalVolume.add(detailModel.getTotalVolume());
			totalWeight = totalWeight.add(detailModel.getTotalWeight());

			TmsAppointmentDetailModel appointmentDetailModel = new TmsAppointmentDetailModel();

			BeanUtils.copyProperties(detailModel, appointmentDetailModel);

			// 获取预约明细表ID
			RestMessage<String> restMessageDetailId = maindataTmsResource.getCodeNumberByCode(SeriaNnumberConstant.TMS_APPOINTMENT_DETAIL_ID, "L");
			if (!restMessageDetailId.isSuccess()) {
				throw new RuntimeException("生成预约明细表ID失败");
			}
			String detailId = restMessageDetailId.getData();
			appointmentDetailModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_APP_ING);
			appointmentDetailModel.setId(detailId);
			appointmentDetailModel.setAppointmentId(id);
			appointmentDetailModel.setAppointmentNo(id);

			appointmentDetailModel.setEnterpriseId(user.getEnterpriseId());
			appointmentDetailModel.setEnterpriseName(user.getEnterpriseName());
			appointmentDetailModel.setCreateperson(user.getNickname());
			appointmentDetailModel.setCreatetime(date);
			if (ToolKits.isEmpty(appointmentConfirmationVO.getShipfromDate())) {
				appointmentDetailModel.setEstimatedPickupStartTime(appStartTime);
				appointmentDetailModel.setEstimatedPickupEndTime(appEndTime);
			}

			// 更新运单状态 为预约中
			Map<String, Object> mapUpdate = Maps.newHashMap();
			if (ToolKits.isEmpty(appointmentConfirmationVO.getShipfromDate())) {
				mapUpdate.put("estimatedPickupStartTime", appStartTime);
				mapUpdate.put("estimatedPickupEndTime", appEndTime);
			}
			mapUpdate.put("status", DataDictionaryConstant.SHIPBILL_STATUS_APP_ING);
			mapUpdate.put("updateperson", user.getNickname());
			mapUpdate.put("updatetime", date);
			tmsShipbillHeaderMapper.updateMapById(detailModel.getShipbillId(), mapUpdate, TmsShipbillHeaderModel.class);

			// 更新装车单明细状态 为预约中
			Criteria criteriaLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r4 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
			Restriction r5 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, detailModel.getShipbillId());
			// STD-DEVELOP20220823 lhb auto check in 20220905 start
			Restriction r6 = Restrictions.eq(TmsLoadingBillDetailModel::getStatus, DataDictionaryConstant.SHIPBILL_STATUS_PENDING_APP);
			criteriaLoadingBillDetail.setRestriction(Restrictions.and(r4, r5, r6));
			// STD-DEVELOP20220823 lhb auto check in 20220905 end

			criteriaLoadingBillDetail.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetails = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);

			tmsLoadingBillDetailMapper.updateMapByCriteria(mapUpdate, criteriaLoadingBillDetail);

			TmsLoadingBillDetailModel tmsLoadingBillDetail = tmsLoadingBillDetails.get(0);
			appointmentDetailModel.setLoadingBillId(tmsLoadingBillDetail.getLoadingBillId());
			tmsAppointmentDetailMapper.save(appointmentDetailModel);

			// 日志表
			ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
			shipbillOperateLogSaveVO.setShipbillId(detailModel.getShipbillId());
			shipbillOperateLogSaveVO.setShipbillNo(detailModel.getShipbillId());
			shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_YYQR);
			shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK);
			shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_APP_ING);
			shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

		}

		appointmentHeaderModel.setUrgentQuantity(jiaJiCnt);
		appointmentHeaderModel.setTotalPcs(totalPcs);
		appointmentHeaderModel.setTotalVolume(totalVolume);
		appointmentHeaderModel.setTotalWeight(totalWeight);

		StringBuffer newNum = new StringBuffer();
		QueryMaxReserveNumberVO numberVO = new QueryMaxReserveNumberVO();
		// 预约号生成
		if (jiaJiCnt > 0) {
			numberVO.setIsJiaJi("1");
			newNum.append(DataDictionaryConstant.RESERVE_NUMBER);
		}
		String appDtStr1 = DateUtil.format(appDt, "yyyyMMdd");
		newNum.append(appDtStr1);
		newNum.append(appTime.substring(0, 2));
		newNum.append(appTime.substring(6, 8));
		numberVO.setAppointmentType(DataDictionaryConstant.APPOINTMENT_TYPE_TH);
		numberVO.setAppointmentDate(appDt);
		numberVO.setAppointmentTime(appTime);
		numberVO.setBranchId(String.valueOf(branchid));

		String maxReserveNumber = tmsAppointmentHeaderMapper.queryMaxReserveNumber(numberVO);
		if (com.prolog.common.util.ToolKits.isNotEmpty(maxReserveNumber)) {
			String oldNum = maxReserveNumber.substring(maxReserveNumber.length() - 3);
			String pattern = "[1-9]+";
			Pattern r = Pattern.compile(pattern);
			Matcher m = r.matcher(oldNum);
			if (m.find()) {
				int num = Integer.valueOf(m.group(0)).intValue() + 1;
				newNum.append(String.format("%03d", num));
			} else {
				newNum.append("001");
			}
		} else {
			newNum.append("001");
		}

		appointmentHeaderModel.setReserveNumber(newNum.toString());
		appointmentHeaderModel.setTallyStatus(DataDictionaryConstant.TALLY_STATUS_WLH);
		if (appointmentConfirmationVO.getFullLink()) {
			appointmentHeaderModel.setCreateMode(AppointCreateModeEnum.SHIP.getCode());
		} else {
			appointmentHeaderModel.setCreateMode(getQueryType());
		}
		tmsAppointmentHeaderMapper.save(appointmentHeaderModel);

		appointmentConfirmationDTO.setDriverId(String.valueOf(driverCheckDTO.getId()));
		appointmentConfirmationDTO.setDriverCode(driverCheckDTO.getCode());
		appointmentConfirmationDTO.setDriverName(driverCheckDTO.getName());
		appointmentConfirmationDTO.setDriverTel(driverCheckDTO.getPhoneNumber());
		appointmentConfirmationDTO.setAppointFromId(appointmentHeaderModel.getBranchId().toString());
		appointmentConfirmationDTO.setAppointFromName(appointmentHeaderModel.getBranchName());
		appointmentConfirmationDTO.setAppointDate(appointmentConfirmationVO.getAppointmentDate() + " " + appointmentConfirmationVO.getAppointTime());
		appointmentConfirmationDTO.setAppointAddress(tmsBaseBranchDTO.getAddress());
		appointmentConfirmationDTO.setShipBillNums(headerModelList.size());
		appointmentConfirmationDTO.setShipBillPackages(totalPcs.intValue());
		appointmentConfirmationDTO.setShipfromDate(appStartTime);
		appointmentConfirmationDTO.setVehiclePlateNumber(appointmentConfirmationVO.getVehiclePlateNumber());
		appointmentConfirmationDTO.setAppointmentBillNo(appointmentHeaderModel.getAppointmentNo());
		appointmentConfirmationDTO.setAppointNumber(newNum.toString());
		MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.APPOINTMENT_NO.getCode(), MessageTypeEnum.APPOINTMENT.getCode(), Lists.newArrayList(id)));
		return appointmentConfirmationDTO;
	}

	private String getQueryType() {
		RestMessage<SysParamConfigModel> restMessage = maindataFeign.getValue(DataDictionaryConstant.DRIVER_APPOINTMENT_SHOW);
		if (!restMessage.isSuccess()) {
			throw new BizException("查询系统参数【" + DataDictionaryConstant.DRIVER_APPOINTMENT_SHOW + "】错误，" + restMessage.getMessage());
		}
		if (ObjectUtil.isNull(restMessage.getData())) {
			throw new BizException("查询系统参数【" + DataDictionaryConstant.DRIVER_APPOINTMENT_SHOW + "】为空");
		}
		return restMessage.getData().getValue();
	}

	/**
	 * 司机预约单信息查询
	 */
	@Override
	public List<AppointmentBillQueryDTO> appointmentBillQuery(AppointmentBillQueryVO appointmentBillQueryVO) throws Exception {
		ToolKits.isParamNull(appointmentBillQueryVO, "司机预约单信息查询请求参数不为空");
		ToolKits.isParamNull(appointmentBillQueryVO.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(appointmentBillQueryVO.getEnterpriseId(), "企业ID不能为空");
		List<AppointmentBillQueryDTO> dtos = tmsAppointmentHeaderMapper.appointmentBillQuery(appointmentBillQueryVO);
		if (ObjectUtils.isEmpty(dtos)) {
			throw new RuntimeException("未找预约数据！");
		}
		return dtos;
	}

	/**
	 * 司机预约单信息查询
	 */
	@Override
	public List<AppointmentBillQueryDTO> appointmentDoingBillQuery(AppointmentBillQueryVO appointmentBillQueryVO) throws Exception {
		ToolKits.isParamNull(appointmentBillQueryVO, "司机预约单信息查询请求参数不为空");
		ToolKits.isParamNull(appointmentBillQueryVO.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(appointmentBillQueryVO.getEnterpriseId(), "企业ID不能为空");
		List<AppointmentBillQueryDTO> dtos = tmsAppointmentHeaderMapper.appointmentDoingBillQuery(appointmentBillQueryVO);
		if (ObjectUtils.isEmpty(dtos)) {
			throw new RuntimeException("未找预约数据！");
		}
		return dtos;
	}

	/**
	 * 司机预约单明细信息查询
	 */
	@Override
	public List<AppointmentBillDetailQueryDTO> appointmentBillDetailQuery(AppointmentBillDetailQueryVO appointmentBillDetailQueryVO) throws Exception {
		ToolKits.isParamNull(appointmentBillDetailQueryVO, "司机预约单信息查询请求参数不为空");
		ToolKits.isParamNull(appointmentBillDetailQueryVO.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(appointmentBillDetailQueryVO.getEnterpriseId(), "企业ID不能为空");
		ToolKits.isParamNull(appointmentBillDetailQueryVO.getAppointmentBillNo(), "预约单号不能为空");
		List<AppointmentBillDetailQueryDTO> dtos = tmsAppointmentHeaderMapper.appointmentBillDetailQuery(appointmentBillDetailQueryVO);
		if (ObjectUtils.isEmpty(dtos)) {
			throw new RuntimeException("未找预约数据！");
		}
		List<AppointmentBillDetailQueryDTO> returndtos = new ArrayList<AppointmentBillDetailQueryDTO>();
		for (AppointmentBillDetailQueryDTO dto : dtos) {
			dto.setLoadingBillId(loadingBillService.getLoadingBillIdByShipBillId(dto.getShipbillId()));
			ShipbillDetailQueryVO vo = new ShipbillDetailQueryVO();
			vo.setEnterpriseId(dto.getEnterpriseId());
			vo.setShipbillId(dto.getShipbillId());
			List<ShipbillItemDetailQueryDTO> itemDetails = tmsShipbillHeaderMapper.shipbillItemDetailQuery(vo);
			dto.setItemDetail(itemDetails);
			dto.setPackageDetailDTOList(pendingReceiptService.getPackageDetailDTO(dto.getShipbillId()));
			returndtos.add(dto);
		}
		return returndtos;
	}

	/**
	 * 预约取消
	 */
	@Override
	public void appointmentCancel(AppointmentCancelVO appointmentCancelVO) throws Exception {
		ToolKits.isParamNull(appointmentCancelVO, "预约取消请求参数不为空");
		ToolKits.isParamNull(appointmentCancelVO.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(appointmentCancelVO.getEnterpriseId(), "企业ID不能为空");
		ToolKits.isParamNull(appointmentCancelVO.getAppointmentBillNo(), "预约单号不能为空");
		// 当前时间
		Date date = DateUtils.nowDate();

		UserEntity user = PlgFxUsrUtils.getUserEntity();
		com.prolog.common.util.ToolKits.isParamNull(user, "当前人员没有操作权限");

		TmsAppointmentHeaderModel tmsAppointmentHeader = tmsAppointmentHeaderMapper.findById(appointmentCancelVO.getAppointmentBillNo(), TmsAppointmentHeaderModel.class);
		tmsAppointmentHeader.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_QX);
		tmsAppointmentHeader.setUpdateperson(user.getNickname());
		tmsAppointmentHeader.setUpdatetime(date);
		tmsAppointmentHeaderMapper.update(tmsAppointmentHeader);

		// 查询预约单明细
		Criteria criteriaDetail = Criteria.forClass(TmsAppointmentDetailModel.class);
		Restriction r1 = Restrictions.eq(TmsAppointmentDetailModel::getEnterpriseId, tmsAppointmentHeader.getEnterpriseId());
		Restriction r2 = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, tmsAppointmentHeader.getAppointmentId());
		criteriaDetail.setRestriction(Restrictions.and(r1, r2));
		List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteriaDetail);

		if (ToolKits.isNotEmpty(tmsAppointmentDetailModels)) {
			// 获取运单id
			List<String> shipbillIds = tmsAppointmentDetailModels.stream().filter(o -> ToolKits.isNotEmpty(o.getShipbillId())).map(TmsAppointmentDetailModel::getShipbillId).collect(Collectors.toList());

			// 封装修改数据集
			Map<String, Object> map = Maps.newHashMap();
			map.put("status", DataDictionaryConstant.SHIPBILL_STATUS_PENDING_APP);
			map.put("updatetime", date);
			map.put("updateperson", user.getNickname());

			// 修改运单状态
			Criteria shipbillHeader = Criteria.forClass(TmsShipbillHeaderModel.class);
			Restriction shipbillId = Restrictions.in("shipbillId", shipbillIds.toArray());
			shipbillHeader.setRestriction(shipbillId);
			tmsShipbillHeaderMapper.updateMapByCriteria(map, shipbillHeader);

			Criteria criteriaLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
			// 运单日志添加
			for (String id : shipbillIds) {
				// 更新装车单明细
				Restriction r3 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, id);
				Restriction r4 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
				criteriaLoadingBillDetail.setRestriction(Restrictions.and(r3, r4));
				criteriaLoadingBillDetail.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
				List<TmsLoadingBillDetailModel> tmsLoadingBillDetails = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);

				if (ToolKits.isEmpty(tmsLoadingBillDetails)) {
					throw new PrologException("运单【" + id + "】查询失败");
				}
				TmsLoadingBillDetailModel billDetailModel = tmsLoadingBillDetails.get(0);
				billDetailModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_PENDING_APP);
				billDetailModel.setUpdateperson(user.getNickname());
				billDetailModel.setUpdatetime(date);
				tmsLoadingBillDetailMapper.update(billDetailModel);

				// 运单操作日志保存
				ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
				shipbillOperateLogSaveNewVO.setShipbillId(id);
				shipbillOperateLogSaveNewVO.setShipbillNo(id);
				shipbillOperateLogSaveNewVO.setOperateDate(date);
				shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
				shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
				shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
				shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
				shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_YYQX);
				shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_PENDING_APP);
				shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_PENDING_APP);
				shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);
			}
		}

		// 封装修改参数
		Map<String, Object> map = Maps.newHashMap();
		map.put("status", DataDictionaryConstant.APPOINTMENT_STATUS_QX);
		map.put("updatetime", date);
		map.put("updateperson", user.getNickname());
		// 取消预约单明细
		tmsAppointmentDetailMapper.updateMapByCriteria(map, criteriaDetail);

	}

}
