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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.prolog.rdc.tms.app.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.app.constant.enums.VoiceBusinessTypeEnum;
import com.prolog.rdc.tms.app.dao.mapper.TmsLoadingBillDetailMapper;
import com.prolog.rdc.tms.app.model.dto.VoiceBroadcastDTO;
import com.prolog.rdc.tms.app.model.dto.VoiceBroadcastItemCodeDTO;
import com.prolog.rdc.tms.app.model.dto.VoiceBroadcastItemDTO;
import com.prolog.rdc.tms.app.model.dto.VoiceBroadcastQueryDataDTO;
import com.prolog.rdc.tms.app.model.vo.VoiceBroadcastQueryVO;
import com.prolog.rdc.tms.app.service.VoiceBroadcastService;
import com.prolog.rdc.tms.app.util.AutoSignJudge;
import com.prolog.rdc.tms.app.util.DistanceUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 语音播报
 * @author hongbo.pan
 */
@Service
@Slf4j
public class VoiceBroadcastServiceImpl implements VoiceBroadcastService {

	@Autowired
	private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

	@Autowired
	private AutoSignJudge autoSignJudge;

	/**
	 * 语音播报查询
	 * @param vo
	 * @return
	 */
	@Override
	public VoiceBroadcastDTO broadcast(VoiceBroadcastQueryVO vo) {
		log.info(Thread.currentThread().getName() +"【司机播报】入参={}", JSON.toJSONString(vo));
		VoiceBroadcastDTO voiceBroadcastDTO = new VoiceBroadcastDTO();
		voiceBroadcastDTO.setDriverId(vo.getDriverId());
		voiceBroadcastDTO.setVehiclePlateNumber(vo.getVehiclePlateNumber());
		List<VoiceBroadcastQueryDataDTO> voiceBroadcastQueryDataDTOList =
				tmsLoadingBillDetailMapper.getBroadcastData(vo);
		log.info(Thread.currentThread().getName() +"【司机播报】状态满足数据={}", JSON.toJSONString(voiceBroadcastQueryDataDTOList));
		if (CollectionUtil.isNotEmpty(voiceBroadcastQueryDataDTOList)) {
			VoiceBroadcastQueryDataDTO voiceBroadcastQueryDataDTO = voiceBroadcastQueryDataDTOList.get(0);
			voiceBroadcastDTO.setDriverName(voiceBroadcastQueryDataDTO.getDriverName());
			voiceBroadcastDTO.setDriverPhoneNumber(voiceBroadcastQueryDataDTO.getDriverPhoneNumber());
			List<VoiceBroadcastItemDTO> voiceBroadcastItemDTOList = Lists.newArrayList();
			List<VoiceBroadcastQueryDataDTO> shipDataDTOList = voiceBroadcastQueryDataDTOList.stream().filter(dto ->
					DataDictionaryConstant.SHIPBILL_STATUS_THQD.equals(dto.getStatus()) ||
							DataDictionaryConstant.SHIPBILL_STATUS_QY.equals(dto.getStatus())).collect(Collectors.toList());
			List<VoiceBroadcastQueryDataDTO> deliveryDataDTOList = voiceBroadcastQueryDataDTOList.stream().filter(dto ->
					DataDictionaryConstant.SHIPBILL_STATUS_SDQD.equals(dto.getStatus()) ||
							DataDictionaryConstant.SHIPBILL_STATUS_SD.equals(dto.getStatus())).collect(Collectors.toList());
			log.info(Thread.currentThread().getName() +"【司机播报】启运状态满足数据={}", JSON.toJSONString(shipDataDTOList));
			log.info(Thread.currentThread().getName() +"【司机播报】送达状态满足数据={}", JSON.toJSONString(deliveryDataDTOList));
			if (CollectionUtil.isNotEmpty(shipDataDTOList)) {
				List<VoiceBroadcastQueryDataDTO> filterShipDataDTOList = shipDataDTOList.stream().filter(shipDataDTO ->
						shipConditionMatch(shipDataDTO, vo)).collect(Collectors.toList());
				log.info(Thread.currentThread().getName() +"【司机播报】启运播报满足数据={}", JSON.toJSONString(filterShipDataDTOList));
				if (CollectionUtil.isNotEmpty(filterShipDataDTOList)) {
					VoiceBroadcastItemDTO voiceBroadcastItemDTO = new VoiceBroadcastItemDTO();
					voiceBroadcastItemDTO.setVoiceBusinessType(VoiceBusinessTypeEnum.SHIP.getCode());
					voiceBroadcastItemDTO.setVoiceBroadcastItemCodeDTOList(transfer(filterShipDataDTOList));
					voiceBroadcastItemDTOList.add(voiceBroadcastItemDTO);
				}
			}
			if (CollectionUtil.isNotEmpty(deliveryDataDTOList)) {
				List<VoiceBroadcastQueryDataDTO> filterDeliveryDataDTOList = deliveryDataDTOList.stream().filter(deliveryDataDTO ->
						deliveryConditionMatch(deliveryDataDTO, vo)).collect(Collectors.toList());
				log.info(Thread.currentThread().getName() +"【司机播报】送达播报满足数据={}", JSON.toJSONString(filterDeliveryDataDTOList));
				if (CollectionUtil.isNotEmpty(filterDeliveryDataDTOList)) {
					VoiceBroadcastItemDTO voiceBroadcastItemDTO = new VoiceBroadcastItemDTO();
					voiceBroadcastItemDTO.setVoiceBusinessType(VoiceBusinessTypeEnum.DELIVERY.getCode());
					voiceBroadcastItemDTO.setVoiceBroadcastItemCodeDTOList(transfer(filterDeliveryDataDTOList));
					voiceBroadcastItemDTOList.add(voiceBroadcastItemDTO);
				}
			}
			voiceBroadcastDTO.setVoiceBroadcastItemDTOList(voiceBroadcastItemDTOList);
		}
		log.info(Thread.currentThread().getName() +"【司机播报】出参={}", JSON.toJSONString(voiceBroadcastDTO));
		return voiceBroadcastDTO;
	}

	/**
	 * 数据转换
	 * @param filterDataDTOList
	 * @return
	 */
	private List<VoiceBroadcastItemCodeDTO> transfer(List<VoiceBroadcastQueryDataDTO> filterDataDTOList) {
		Map<String, List<VoiceBroadcastQueryDataDTO>> shipMap = filterDataDTOList.stream().collect(Collectors.groupingBy(VoiceBroadcastQueryDataDTO::getLoadingBillId));
		List<VoiceBroadcastItemCodeDTO> voiceBroadcastItemCodeDTOList = Lists.newArrayList();
		shipMap.forEach((key, value) -> {
			VoiceBroadcastItemCodeDTO voiceBroadcastItemCodeDTO = new VoiceBroadcastItemCodeDTO();
			voiceBroadcastItemCodeDTO.setLoadingBillId(key);
			voiceBroadcastItemCodeDTO.setShipBillIdList(value.stream().map(VoiceBroadcastQueryDataDTO::getShipbillId).collect(Collectors.toList()));
			voiceBroadcastItemCodeDTOList.add(voiceBroadcastItemCodeDTO);
		});
		return voiceBroadcastItemCodeDTOList;
	}

	/**
	 * 启运播报条件是否满足
	 * @param shipDataDTO
	 * @param vo
	 * @return
	 */
	private Boolean shipConditionMatch(VoiceBroadcastQueryDataDTO shipDataDTO, VoiceBroadcastQueryVO vo) {
		Boolean shipDistanceCondition = ObjectUtil.isNotNull(shipDataDTO.getShipperLatitude()) &&
				ObjectUtil.isNotNull(shipDataDTO.getShipperLongitude()) &&
				ObjectUtil.isNotNull(shipDataDTO.getShipperPickUpRail());
		if (shipDistanceCondition) {
			double distance = DistanceUtil.getDistance(shipDataDTO.getShipperLongitude().doubleValue(), shipDataDTO.getShipperLatitude().doubleValue(),
					vo.getLongitude().doubleValue(), vo.getLatitude().doubleValue());
			// 必须距离在范围内
			Boolean shipDistance = NumberUtil.isLess(BigDecimal.valueOf(distance), shipDataDTO.getShipperPickUpRail());
			if (shipDistance) {
				// 没有设置签到时间点 可以任意时间签到
				Boolean shipSignTimeCondition = ObjectUtil.isNotNull(shipDataDTO.getShipperSignTime()) &&
						ObjectUtil.isNotNull(shipDataDTO.getShipperSignTimeUnit()) &&
						ObjectUtil.isNotNull(shipDataDTO.getShipperSignTimeDura());
				if (shipSignTimeCondition) {
					return autoSignJudge.autoSignJudge(shipDataDTO.getShipbillId(), "1");
				}
				log.info(Thread.currentThread().getName() +"【司机播报】【发货方】没有设置签到时间相关数据，可以任意时间签到，shipDataDTO={}，vo={}", JSON.toJSONString(shipDataDTO), JSON.toJSONString(vo));
				return true;
			}
			log.info(Thread.currentThread().getName() +"【司机播报】【发货方】当前定位不在围栏范围内distance={}，shipDataDTO={}，vo={}", distance, JSON.toJSONString(shipDataDTO), JSON.toJSONString(vo));
			return false;
		}
		log.info(Thread.currentThread().getName() +"【司机播报】【发货方】经纬度围栏数据不存在shipDataDTO={}，vo={}", JSON.toJSONString(shipDataDTO), JSON.toJSONString(vo));
		return false;
	}

	/**
	 * 送达播报条件是否满足
	 * @param deliveryDataDTO
	 * @param vo
	 * @return
	 */
	private Boolean deliveryConditionMatch(VoiceBroadcastQueryDataDTO deliveryDataDTO, VoiceBroadcastQueryVO vo) {
		Boolean deliveryDistanceCondition = ObjectUtil.isNotNull(deliveryDataDTO.getConsigneeLatitude()) &&
				ObjectUtil.isNotNull(deliveryDataDTO.getConsigneeLongitude()) &&
				ObjectUtil.isNotNull(deliveryDataDTO.getConsigneeDeliveryRail());
		if (deliveryDistanceCondition) {
			double distance = DistanceUtil.getDistance(deliveryDataDTO.getConsigneeLongitude().doubleValue(), deliveryDataDTO.getConsigneeLatitude().doubleValue(),
					vo.getLongitude().doubleValue(), vo.getLatitude().doubleValue());
			// 必须距离在范围内
			Boolean shipDistance = NumberUtil.isLess(BigDecimal.valueOf(distance), deliveryDataDTO.getConsigneeDeliveryRail());
			if (shipDistance) {
				// 没有设置签到时间点 可以任意时间签到
				Boolean shipSignTimeCondition = ObjectUtil.isNotNull(deliveryDataDTO.getConsigneeSignTime()) &&
						ObjectUtil.isNotNull(deliveryDataDTO.getConsigneeSignTimeUnit()) &&
						ObjectUtil.isNotNull(deliveryDataDTO.getConsigneeSignTimeDura());
				if (shipSignTimeCondition) {
					return autoSignJudge.autoSignJudge(deliveryDataDTO.getShipbillId(), "2");
				}
				log.info(Thread.currentThread().getName() +"【司机播报】【收货方】没有设置签到时间相关数据，可以任意时间签到，deliveryDataDTO={}，vo={}", JSON.toJSONString(deliveryDataDTO), JSON.toJSONString(vo));
				return true;
			}
			log.info(Thread.currentThread().getName() +"【司机播报】【收货方】当前定位不在围栏范围内，distance={}，deliveryDataDTO={}，vo={}", distance, JSON.toJSONString(deliveryDataDTO), JSON.toJSONString(vo));
			return false;
		}
		log.info(Thread.currentThread().getName() +"【司机播报】【收货方】经纬度围栏数据不存在deliveryDataDTO={}，vo={}", JSON.toJSONString(deliveryDataDTO), JSON.toJSONString(vo));
		return false;
	}
}
