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

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.prolog.common.util.ToolKits;
import com.prolog.framework.core.restriction.Criteria;
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.dao.mapper.TmsAppointmentDetailMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsAppointmentHeaderMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsLoadingBillDetailMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsLoadingBillHeaderMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillHeaderMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillNodeTrackingMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillOperateLogMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillTransportLogMapper;
import com.prolog.rdc.tms.app.model.dto.AppointmentConfirmationDTO;
import com.prolog.rdc.tms.app.model.dto.PendingFullLinkQueryDTO;
import com.prolog.rdc.tms.app.model.dto.PendingPickUpDetailQueryDTO;
import com.prolog.rdc.tms.app.model.dto.ShipbillItemDetailQueryDTO;
import com.prolog.rdc.tms.app.model.entity.TmsLoadingBillDetailModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillTransLogModel;
import com.prolog.rdc.tms.app.model.vo.AppointmentConfirmationVO;
import com.prolog.rdc.tms.app.model.vo.AutoCheckInVO;
import com.prolog.rdc.tms.app.model.vo.FullLinkAppointmentConfirmationVO;
import com.prolog.rdc.tms.app.model.vo.PendingDeliverySignInVO;
import com.prolog.rdc.tms.app.model.vo.PendingFullLinkPickUpSignInVO;
import com.prolog.rdc.tms.app.model.vo.PendingFullLinkPickUpStartShipmentVO;
import com.prolog.rdc.tms.app.model.vo.PendingFullLinkQueryVO;
import com.prolog.rdc.tms.app.model.vo.PendingPickUpSignInVO;
import com.prolog.rdc.tms.app.model.vo.PendingPickUpStartShipmentVO;
import com.prolog.rdc.tms.app.model.vo.ShipbillDetailQueryVO;
import com.prolog.rdc.tms.app.service.PendingAppointmentService;
import com.prolog.rdc.tms.app.service.PendingDeliveryService;
import com.prolog.rdc.tms.app.service.PendingFullLinkService;
import com.prolog.rdc.tms.app.service.PendingPickUpService;
import com.prolog.rdc.tms.app.util.DistanceUtil;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;

/**
 *
 *
 * 司机APP-全链路实现层
 *
 * @className :PendingFullLinkServiceImpl
 * @author :qian.yh
 * @creationTime :2022/08/15
 * @description :
 *
 * @modifier :
 * @modifyTime :
 * @reviseRemarks:
 *
 * @version :1.0.0
 *
 */
@Service
public class PendingFullLinkServiceImpl implements PendingFullLinkService {
	@Resource
	private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

	@Resource
	private MaindataFeign maindataTmsResource;

	@Resource
	private TmsAppointmentHeaderMapper tmsAppointmentHeaderMapper;

	@Resource
	private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

	@Resource
	private TmsAppointmentDetailMapper tmsAppointmentDetailMapper;

	@Resource
	private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

	@Resource
	private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

	@Resource
	private TmsShipbillNodeTrackingMapper tmsShipbillNodeTrackingMapper;

	@Resource
	private TmsShipbillOperateLogMapper tmsShipbillOperateLogMapper;

	// STD-DEVELOP20220823 lhb auto check in 20220905 start
	@Resource
	private PendingPickUpService pendingPickUpService;

	@Resource
	private PendingDeliveryService pendingDeliveryService;

	@Resource
	PendingAppointmentService pendingAppointmentService;
	// STD-DEVELOP20220823 lhb auto check in 20220905 end

	@Override
	public List<PendingFullLinkQueryDTO> pendingFullLinkQuery(PendingFullLinkQueryVO pendingFullLinkQueryVO) throws Exception {
		ToolKits.isParamNull(pendingFullLinkQueryVO, "司机待预约明细查询请求参数不为空");
		ToolKits.isParamNull(pendingFullLinkQueryVO.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(pendingFullLinkQueryVO.getVehiclePlateNumber(), "车牌号不为空");
		ToolKits.isParamNull(pendingFullLinkQueryVO.getEnterpriseId(), "企业ID不能为空");
		List<PendingFullLinkQueryDTO> dtos = tmsShipbillHeaderMapper.pendingFullLinkQuery(pendingFullLinkQueryVO);
		if (ObjectUtils.isEmpty(dtos)) {
			throw new RuntimeException("未找到对应的运单明细！");
		}
		// STD-DEVELOP20220823 lhb auto check in 20220905 start
		// 判断是否 自动提货签到
		if (ToolKits.isNotEmpty(pendingFullLinkQueryVO.getDriverLongitude()) && ToolKits.isNotEmpty(pendingFullLinkQueryVO.getDriverLatitude())) {
			List<String> autoCheckInShipbills = Lists.newArrayList();
			for (PendingFullLinkQueryDTO fullLinkQueryDTO : dtos) {
				if (fullLinkQueryDTO.getStatus().equals(DataDictionaryConstant.SHIPBILL_STATUS_QY)) {
					// 提货签到
					if (fullLinkQueryDTO.getShipperPickUpRail().doubleValue() > 0 && ToolKits.isNotEmpty(fullLinkQueryDTO.getShipfromLongitude()) && ToolKits.isNotEmpty(fullLinkQueryDTO.getShipfromLatitude()) && fullLinkQueryDTO.getShipperPickUpSign().intValue() > 0 && fullLinkQueryDTO.getShipperAutoPickUpSign().intValue() > 0) {
						// 司机和仓库之间的距离
						double pos = DistanceUtil.getDistance(pendingFullLinkQueryVO.getDriverLongitude().doubleValue(), pendingFullLinkQueryVO.getDriverLatitude().doubleValue(), Double.valueOf(fullLinkQueryDTO.getShipfromLongitude()).doubleValue(), Double.valueOf(fullLinkQueryDTO.getShipfromLatitude()).doubleValue());
						if (Double.compare(pos, fullLinkQueryDTO.getShipperPickUpRail().doubleValue()) <= 0) {
							PendingPickUpSignInVO pickUpSignInVO = new PendingPickUpSignInVO();
							pickUpSignInVO.setShipbillIds(fullLinkQueryDTO.getShipbillId());
							pendingPickUpService.pendingPickUpSignIn(pickUpSignInVO);
							fullLinkQueryDTO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_THQD);
						}
					}
				} else if (fullLinkQueryDTO.getStatus().equals(DataDictionaryConstant.SHIPBILL_STATUS_SD)) {
					// 送达签到
					if (fullLinkQueryDTO.getConsigneeDeliveryRail().doubleValue() > 0 && ToolKits.isNotEmpty(fullLinkQueryDTO.getShipToLongitude()) && ToolKits.isNotEmpty(fullLinkQueryDTO.getShipToLatitude()) && fullLinkQueryDTO.getConsigneeDeliverySign().intValue() > 0 && fullLinkQueryDTO.getConsigneeAutoDeliverySign().intValue() > 0) {
						// 司机和仓库之间的距离
						double pos = DistanceUtil.getDistance(pendingFullLinkQueryVO.getDriverLongitude().doubleValue(), pendingFullLinkQueryVO.getDriverLatitude().doubleValue(), Double.valueOf(fullLinkQueryDTO.getShipToLongitude()).doubleValue(), Double.valueOf(fullLinkQueryDTO.getShipToLatitude()).doubleValue());
						if (Double.compare(pos, fullLinkQueryDTO.getConsigneeDeliveryRail().doubleValue()) <= 0) {
							// 调用自动签到
							PendingDeliverySignInVO deliverySignInVO = new PendingDeliverySignInVO();
							deliverySignInVO.setShipbillId(fullLinkQueryDTO.getShipbillId());
							deliverySignInVO.setDriverId(fullLinkQueryDTO.getDriverId());
							deliverySignInVO.setEnterpriseId(pendingFullLinkQueryVO.getEnterpriseId());
							pendingDeliveryService.pendingDeliverySignIn(deliverySignInVO);

							fullLinkQueryDTO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_SDQD);
						}
					}
				}
			}
		}
		// STD-DEVELOP20220823 lhb auto check in 20220905 end

		List<PendingFullLinkQueryDTO> returndtos = new ArrayList<>();
		for (PendingFullLinkQueryDTO dto : dtos) {
			ShipbillDetailQueryVO vo = new ShipbillDetailQueryVO();
			vo.setEnterpriseId(dto.getEnterpriseId());
			vo.setShipbillId(dto.getShipbillId());
			List<ShipbillItemDetailQueryDTO> itemDetails = tmsShipbillHeaderMapper.shipbillItemDetailQuery(vo);
			dto.setItemDetail(itemDetails);
			returndtos.add(dto);
		}
		return returndtos;
	}

	/**
	 * 预约确认
	 */
	@Override
	public AppointmentConfirmationDTO fullLinkAppointmentConfirmation(FullLinkAppointmentConfirmationVO vo) throws Exception {
		ToolKits.isParamNull(vo, "提货预约确认请求不为空");
		ToolKits.isParamNull(vo.getAppointmentDate(), "预约日期不为空");
		ToolKits.isParamNull(vo.getEnterpriseId(), "企业不能为空");
		ToolKits.isParamNull(vo.getDriverId(), "司机不为空");
		ToolKits.isParamNull(vo.getVehiclePlateNumber(), "车牌号不为空");
		ToolKits.isParamNull(vo.getId(), "调度单明细ID不为空");
		ToolKits.isParamNull(vo.getAppointTime(), "预约时间不为空");

		// STD-DEVELOP20220823 lhb auto check in 20220905 start
		ToolKits.isParamNull(vo.getShipbillId(), "运单ID不为空");
		AppointmentConfirmationVO confirmationVO = new AppointmentConfirmationVO();
		BeanUtils.copyProperties(vo, confirmationVO);
		confirmationVO.setShipbillIds(vo.getShipbillId());
		confirmationVO.setFullLink(Boolean.TRUE);
		AppointmentConfirmationDTO confirmationDTO = pendingAppointmentService.appointmentConfirmation(confirmationVO);
		return confirmationDTO;
		// STD-DEVELOP20220823 lhb auto check in 20220905 end
	}

	@Override
	public void pendingFullLinkPickUpSignIn(PendingFullLinkPickUpSignInVO pendingPickUpSignInVO) throws Exception {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		com.prolog.common.util.ToolKits.isParamNull(user, "当前人员没有操作权限");
		// STD-DEVELOP20220823 lhb auto check in 20220905 start
		com.prolog.common.util.ToolKits.isParamNull(pendingPickUpSignInVO.getShipbillId(), "运单ID不能为空");

		PendingPickUpSignInVO pickUpSignInVO = new PendingPickUpSignInVO();
		pickUpSignInVO.setShipbillIds(pendingPickUpSignInVO.getShipbillId());
		pendingPickUpService.pendingPickUpSignIn(pickUpSignInVO);
		// STD-DEVELOP20220823 lhb auto check in 20220905 end
	}

	@Override
	public List<PendingPickUpDetailQueryDTO> pendingFullLinkPickUpStartShipment(PendingFullLinkPickUpStartShipmentVO pendingPickUpStartShipmentVO) throws Exception {
		ToolKits.isParamNull(pendingPickUpStartShipmentVO, "司机待预约明细查询请求参数不为空");
		ToolKits.isParamNull(pendingPickUpStartShipmentVO.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(pendingPickUpStartShipmentVO.getVehiclePlateNumber(), "车牌号不为空");
		ToolKits.isParamNull(pendingPickUpStartShipmentVO.getEnterpriseId(), "企业ID不能为空");
		ToolKits.isParamNull(pendingPickUpStartShipmentVO.getId(), "调度单明细ID不能为空");

		PendingPickUpStartShipmentVO pickUpStartShipmentVO = new PendingPickUpStartShipmentVO();
		BeanUtils.copyProperties(pendingPickUpStartShipmentVO, pickUpStartShipmentVO);
		pickUpStartShipmentVO.setShipbillIds(pendingPickUpStartShipmentVO.getShipbillId());
		List<PendingPickUpDetailQueryDTO> returndtos = pendingPickUpService.pendingPickUpStartShipment(pickUpStartShipmentVO);
		return returndtos;
	}

	@Override
	public void autoCheckIn(AutoCheckInVO autoCheckInVO) throws Exception {
		ToolKits.isParamNull(autoCheckInVO, "自动签到请求参数不为空");
		ToolKits.isParamNull(autoCheckInVO.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(autoCheckInVO.getVehiclePlateNumber(), "车牌号不为空");
		ToolKits.isParamNull(autoCheckInVO.getEnterpriseId(), "企业ID不能为空");

		UserEntity user = PlgFxUsrUtils.getUserEntity();
		com.prolog.common.util.ToolKits.isParamNull(user, "当前人员没有操作权限");
		// 获取需要自动启运签到的运单
		List<TmsLoadingBillDetailModel> modelList = tmsLoadingBillDetailMapper.queryAutoPickUpSignBillData(autoCheckInVO);
		if (ObjectUtils.isNotNull(modelList)) {
			for (TmsLoadingBillDetailModel model : modelList) {
				if (ObjectUtils.isNotNull(model.getConsigneeLongitude()) && ObjectUtils.isNotNull(model.getConsigneeLatitude()) && ObjectUtils.isNotNull(model.getConsigneeDeliveryRail())) {
					// 判断是否在围栏范围内
					double currLongitude = Double.parseDouble(autoCheckInVO.getCurrLongitude());
					double currLatitude = Double.parseDouble(autoCheckInVO.getCurrLatitude());
					double addressLongitude = model.getConsigneeLongitude().doubleValue();
					double addressLatitude = model.getConsigneeLatitude().doubleValue();
					double fenceRail = model.getConsigneeDeliveryRail().doubleValue();
					if (inFenceRange(currLongitude, currLatitude, addressLongitude, addressLatitude, fenceRail)) {
						// 更新运单状态 为预约中
						Map<String, Object> mapUpdate = Maps.newHashMap();
						mapUpdate.put("departureSignTime", new Date());
						mapUpdate.put("updateperson", user.getNickname());
						mapUpdate.put("updatetime", new Date());

						// 更新装车单明细状态 为预约中
						Criteria criteriaTransportLog = Criteria.forClass(TmsShipbillTransLogModel.class);
						Restriction r4 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, model.getEnterpriseId());
						Restriction r5 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, model.getShipbillId());
						criteriaTransportLog.setRestriction(Restrictions.and(r4, r5));
						tmsShipbillTransportLogMapper.updateMapByCriteria(mapUpdate, criteriaTransportLog);
					}

				}

			}
		}
		// 获取需要自动送达签到的运单
		modelList = tmsLoadingBillDetailMapper.queryAutoDeliverySignBillData(autoCheckInVO);
		if (ObjectUtils.isNotNull(modelList)) {
			for (TmsLoadingBillDetailModel model : modelList) {
				if (ObjectUtils.isNotNull(model.getShipperLongitude()) && ObjectUtils.isNotNull(model.getShipperLatitude()) && ObjectUtils.isNotNull(model.getShipperPickUpRail())) {
					// 判断是否在围栏范围内
					double currLongitude = Double.parseDouble(autoCheckInVO.getCurrLongitude());
					double currLatitude = Double.parseDouble(autoCheckInVO.getCurrLatitude());
					double addressLongitude = model.getShipperLongitude().doubleValue();
					double addressLatitude = model.getShipperLatitude().doubleValue();
					double fenceRail = model.getShipperPickUpRail().doubleValue();
					if (inFenceRange(currLongitude, currLatitude, addressLongitude, addressLatitude, fenceRail)) {
						// 更新运单状态 为预约中
						Map<String, Object> mapUpdate = Maps.newHashMap();
						mapUpdate.put("departureSignTime", new Date());
						mapUpdate.put("updateperson", user.getNickname());
						mapUpdate.put("updatetime", new Date());

						// 更新装车单明细状态 为预约中
						Criteria criteriaTransportLog = Criteria.forClass(TmsShipbillTransLogModel.class);
						Restriction r4 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, model.getEnterpriseId());
						Restriction r5 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, model.getShipbillId());
						criteriaTransportLog.setRestriction(Restrictions.and(r4, r5));
						tmsShipbillTransportLogMapper.updateMapByCriteria(mapUpdate, criteriaTransportLog);
					}
				}
			}
		}
	}

	private static final double EARTH_RADIUS = 6378137.0;

	private static double rad(double d) {
		return d * Math.PI / 180.0;
	}

	private boolean inFenceRange(double currLongitude, double currLatitude, double addressLongitude, double addressLatitude, double fenceRail) {
		double radLat1 = rad(currLatitude);
		double radLat2 = rad(addressLatitude);
		double radLat = radLat1 - radLat2;
		double radLng = rad(currLongitude) - rad(addressLongitude);
		double distance = Math.round(EARTH_RADIUS * 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(radLat / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(radLng / 2), 2))));
		if (distance < fenceRail) {
			return true;
		} else {
			return false;
		}
	}

}
