package com.sckw.transport.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.sckw.contract.api.RemoteContractService;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.model.constant.UrlConstants;
import com.sckw.core.model.enums.AddressTypeEnum;
import com.sckw.core.model.enums.CarWaybillEnum;
import com.sckw.core.utils.DateUtils;
import com.sckw.core.utils.HttpUtil;
import com.sckw.core.web.constant.CommonConstants;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.result.PageDataResult;
import com.sckw.fleet.api.RemoteFleetService;
import com.sckw.fleet.api.model.vo.RDriverVo;
import com.sckw.fleet.api.model.vo.RFleetDriverVo;
import com.sckw.fleet.api.model.vo.RTruckVo;
import com.sckw.manage.api.RemoteManageService;
import com.sckw.order.api.dubbo.RemoteTradeOrderAmountService;
import com.sckw.order.api.dubbo.TradeOrderInfoService;
import com.sckw.payment.api.dubbo.PaymentDubboService;
import com.sckw.product.api.dubbo.GoodsInfoService;
import com.sckw.redis.utils.RedissonUtils;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.EntCacheResDto;
import com.sckw.system.api.model.dto.res.KwsEnterpriseResDto;
import com.sckw.transport.common.config.UrlConfigProperties;
import com.sckw.transport.model.KwtLogisticsOrderUnit;
import com.sckw.transport.model.KwtWaybillOrder;
import com.sckw.transport.model.KwtWaybillOrderAddress;
import com.sckw.transport.model.KwtWaybillOrderSubtask;
import com.sckw.transport.model.dto.TruckDto;
import com.sckw.transport.model.dto.VehicleDataDTO;
import com.sckw.transport.model.dto.VehicleReturnData;
import com.sckw.transport.model.param.CurrentTaskTraceReq;
import com.sckw.transport.model.param.KwfTruckTraceReplayReq;
import com.sckw.transport.model.param.TruckInfoReq;
import com.sckw.transport.model.param.VehiclesTrajectoryReq;
import com.sckw.transport.model.vo.CurrentTaskTraceReqVo;
import com.sckw.transport.model.vo.KwfTruckTraceReplayVo;
import com.sckw.transport.model.vo.TruckInfoVo;
import com.sckw.transport.repository.KwtLogisticsOrderUnitRepository;
import com.sckw.transport.repository.KwtWaybillOrderAddressRepository;
import com.sckw.transport.repository.KwtWaybillOrderRepository;
import com.sckw.transport.repository.KwtWaybillOrderSubtaskRepository;
import com.sckw.transport.response.CollectZjxlResponse;
import com.sckw.transport.service.zj.VehicleCollectService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * @author PC
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class kwfTruckTraceService {
    private final KwtWaybillOrderRepository kwtWaybillOrderRepository;
    private final KwtWaybillOrderAddressRepository kwtWaybillOrderAddressRepository;
    private final UrlConfigProperties urlConfigProperties;
    private final KwtWaybillOrderSubtaskRepository kwtWaybillOrderSubtaskRepository;
    private final VehicleCollectService vehicleCollectService;
    private final KwtLogisticsOrderUnitRepository kwtLogisticsOrderUnitRepository;
    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    RemoteSystemService remoteSystemService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    TradeOrderInfoService tradeOrderInfoService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    RemoteTradeOrderAmountService tradeOrderAmountService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    GoodsInfoService goodsInfoService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    RemoteFleetService fleetService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
    RemoteContractService remoteContractService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
    RemoteManageService remoteManageService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
    PaymentDubboService paymentDubboService ;

    public PageDataResult<KwfTruckTraceReplayVo> findPage(KwfTruckTraceReplayReq req) {
        log.info("查询历轨迹回放参数：{}", req);
        if (StringUtils.isBlank(req.getTruckNo())){
            return PageDataResult.empty(req.getPageNum(), req.getPageSize());
        }
        Date date = new Date();
        if (StringUtils.isNotBlank(req.getStartTime())){
            date = DateUtils.formatDate(req.getStartTime());
        }
        Date beforeDate = DateUtils.addDateDays(date, -30);
        if (StringUtils.isNotBlank(req.getEndTime())){
            beforeDate = DateUtils.formatDate(req.getEndTime());
        }
        Page<KwtWaybillOrder> page = kwtWaybillOrderRepository.findPage(req.getTruckNo(),req.getPageNum(), req.getPageSize(), beforeDate, date);
        List<KwtWaybillOrder> records = page.getRecords();
        if(CollectionUtils.isEmpty(page.getRecords())) {
            return PageDataResult.success(req.getPageNum(), req.getPageSize(),0L, null);
        }
        //查询企业 获取承运单位
        List<Long> entIds = records.stream().map(KwtWaybillOrder::getEntId).distinct().collect(Collectors.toList());
        //运单id
        List<Long> wOrderIds = records.stream().map(KwtWaybillOrder::getId).collect(Collectors.toList());
        //通过运单号查询订单
        List<KwtWaybillOrderSubtask> waybillOrderSubtasks = kwtWaybillOrderSubtaskRepository.queryByWOrderIds(wOrderIds);

        //关联订单id
        Set<Long>  lOrderIds = null;
        //订单号映射订单对象
        Map<String, KwtWaybillOrderSubtask> worderNoAndWorderMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(waybillOrderSubtasks)){
            lOrderIds = waybillOrderSubtasks.stream().map(KwtWaybillOrderSubtask::getLOrderId).collect(Collectors.toSet());
            worderNoAndWorderMap = waybillOrderSubtasks.stream()
                    .collect(Collectors.toMap(KwtWaybillOrderSubtask::getWOrderNo, Function.identity(), (k1, k2) -> k1));
        }

        List<KwtLogisticsOrderUnit> logisticsOrderUnits = kwtLogisticsOrderUnitRepository.queryByLOrderIdsAndUnitType(lOrderIds,2);
        //物流订单id映射企业
        Map<Long, KwtLogisticsOrderUnit> lOrderIdAndLogisticsOrderUnitMap = logisticsOrderUnits.stream()
                .collect(Collectors.toMap(KwtLogisticsOrderUnit::getLOrderId, Function.identity(), (k1, k2) -> k1));
        //通过企业id映射企业信息
        Map<Long, KwsEnterpriseResDto> idAndKwsEnterpriseMap = remoteSystemService.queryEnterpriseByEntIds(entIds);

        //装货地址和卸货地址 kwt_waybill_order_address
        List<KwtWaybillOrderAddress> orderAddresses = kwtWaybillOrderAddressRepository.queryBywOrderIds(wOrderIds);

        //运单id和状态组合key映射地址
        Map<Long, List<KwtWaybillOrderAddress>> wOrderIdAndAddressMap = orderAddresses.stream()
                .collect(Collectors.groupingBy(KwtWaybillOrderAddress::getWOrderId));

        Map<String, KwtWaybillOrderSubtask> finalWorderNoAndWorderMap = worderNoAndWorderMap;
        List<KwfTruckTraceReplayVo> kwfTruckTraceReplayVoList = records.stream()
                .map(r -> getKwfTruckTraceReplayVo(r, idAndKwsEnterpriseMap, wOrderIdAndAddressMap, lOrderIdAndLogisticsOrderUnitMap, finalWorderNoAndWorderMap))
                .collect(Collectors.toList());
       return PageDataResult.of(page,kwfTruckTraceReplayVoList);
    }

    /**
     * 组织轨迹回访返回数据
     * @param waybillOrder 运单信息
     * @param idAndKwsEnterpriseMap 企业id映射企业信息map
     * @param wOrderIdAndAddressMap 运单id映射地址map
     * @return 轨迹回访返回数据
     */
    private static KwfTruckTraceReplayVo getKwfTruckTraceReplayVo(KwtWaybillOrder waybillOrder, Map<Long, KwsEnterpriseResDto> idAndKwsEnterpriseMap,
                                                                  Map<Long, List<KwtWaybillOrderAddress>> wOrderIdAndAddressMap
                                                                ,Map<Long, KwtLogisticsOrderUnit> lOrderIdAndLogisticsOrderUnitMap
                                                                ,Map<String, KwtWaybillOrderSubtask> worderNoAndWorderMap) {

        KwfTruckTraceReplayVo kwfTruckTraceReplay = new KwfTruckTraceReplayVo();
        kwfTruckTraceReplay.setOrderId(waybillOrder.getId());
        kwfTruckTraceReplay.setOrderNo(waybillOrder.getWOrderNo());
        kwfTruckTraceReplay.setDriverName(waybillOrder.getDriverName());
        kwfTruckTraceReplay.setPhone(waybillOrder.getDriverPhone());
        kwfTruckTraceReplay.setStatus(String.valueOf(waybillOrder.getStatus()));
        kwfTruckTraceReplay.setStatusDesc(CarWaybillEnum.getName(waybillOrder.getStatus()));
        KwtWaybillOrderSubtask subtask = worderNoAndWorderMap.getOrDefault(waybillOrder.getWOrderNo(), new KwtWaybillOrderSubtask());
        kwfTruckTraceReplay.setRelationTaskNo(String.valueOf(subtask.getLOrderId()));
        KwtLogisticsOrderUnit kwtLogisticsOrderUnit = lOrderIdAndLogisticsOrderUnitMap.getOrDefault(subtask.getLOrderId(), new KwtLogisticsOrderUnit());
        KwsEnterpriseResDto orDefault = idAndKwsEnterpriseMap.getOrDefault(kwtLogisticsOrderUnit.getEntId(), new KwsEnterpriseResDto());
        kwfTruckTraceReplay.setCarrier(orDefault.getFirmName());
        List<KwtWaybillOrderAddress> addressList = wOrderIdAndAddressMap.get(waybillOrder.getId());
        addressList.forEach(e -> {
            if (Objects.equals(e.getAddressType(), AddressTypeEnum.SHIPMENT.getCode())){
                kwfTruckTraceReplay.setStartAddress(e.getDetailAddress());
            }
            if (Objects.equals(e.getAddressType(),AddressTypeEnum.TAKE.getCode())){
                kwfTruckTraceReplay.setEndAddress(e.getDetailAddress());
            }
        });


        String taskStartEndTime = DateUtils.format(waybillOrder.getTaskStartTime(), DateUtils.DATE_TIME_PATTERN);
        kwfTruckTraceReplay.setTaskStartTime(StringUtils.equals(taskStartEndTime, CommonConstants.DATE_TIME) ? StringUtils.EMPTY: taskStartEndTime);

        String endStartEndTime = DateUtils.format(waybillOrder.getTaskEndTime(), DateUtils.DATE_TIME_PATTERN);
        kwfTruckTraceReplay.setTaskEndTime(StringUtils.equals(endStartEndTime, CommonConstants.DATE_TIME) ? StringUtils.EMPTY: endStartEndTime);
        kwfTruckTraceReplay.setWarningCount("");
        return kwfTruckTraceReplay;
    }

    /**
     * 查询车辆实时位置信息
     * @param req 查询参数
     * @return 车辆实时位置信息
     */
    public TruckInfoVo queryTruckInfo(TruckInfoReq req) {
        log.info("查询车辆实时位置信息参数：{}", req);
        //先查缓存 缓存没有 在查询数据中台 数据中台没有 则查询中交
        if (StringUtils.isNotBlank(req.getTruckId()) ){
            return getTruckInfo(req.getTruckId(),req.getOrderNo(),req.getTruckNo());
        }

        //如果车牌为空那么查询车队的第一条数据 （从tab页面直接进来）
        if (StringUtils.isNotBlank(req.getEntId())){
            RTruckVo dataFirstTruck = fleetService.findDataFirstTruck(Long.valueOf(req.getEntId()));
            if (Objects.isNull(dataFirstTruck) || Objects.isNull(dataFirstTruck.getTruckNo())){
                return new TruckInfoVo();
            }
            return getTruckInfo(req.getTruckId(),req.getOrderNo(),dataFirstTruck.getTruckNo());
        }
        return new TruckInfoVo();
    }

    private TruckInfoVo getTruckInfo(String truckId, String wOrderNo,String truckNo) {
        //先查询缓存 如果缓存没有就查数据中台 数据中台没有就查中交
        String location = RedissonUtils.getString(CommonConstants.TRUCK_LOCATION + truckId+CommonConstants.UNDERSCORE+wOrderNo);
        if (StringUtils.isNotBlank(location)){
            TruckDto truckDto = JSON.parseObject(location, TruckDto.class);
            //如果运单号为空那么返回redis的数据 这个数据是app最后一次上报的数据
            if (Objects.nonNull(truckDto)){
                return getTruckInfoVo(truckId, truckDto);
            }
        }

        //缓存没有则查询数据中台
        VehicleReturnData vehicleReturnData = getVehicleReturnData(truckId);
        if (Objects.nonNull(vehicleReturnData)){
            saveRedisCache(truckId, wOrderNo, truckNo, vehicleReturnData);
            return buildTruckInfo(truckId, vehicleReturnData, truckNo);
        }
        //todo 查询中交 如果数据中台没有数据则查询中交
       // return getTruckInfoVoByZj(truckNo, wOrderNo,truckId);
        return new TruckInfoVo();

    }


    private TruckInfoVo getTruckInfoVo(String truckId, TruckDto truckDto) {
        TruckInfoVo truckInfoVo = TruckInfoVo.toTruckInfoVo(truckDto);
        truckInfoVo.setGpsStatus(truckDto.getGpsStatus());
        truckInfoVo.setLongitude(truckDto.getLongitude());
        truckInfoVo.setLatitude(truckDto.getLatitude());
        truckInfoVo.setLocationTime(truckDto.getLocationTime());
        truckInfoVo.setTaskAddress(truckDto.getTaskAddress());
        KwtWaybillOrder order = kwtWaybillOrderRepository.findOneByTruckId(truckId);
        if (Objects.nonNull(order)){
            truckInfoVo.setTruckNo(order.getTruckNo());
            truckInfoVo.setOrderNo(order.getWOrderNo());
            truckInfoVo.setDriveId(String.valueOf(order.getDriverId()));
            truckInfoVo.setDriveName(order.getDriverName());
            truckInfoVo.setDrivePhone(order.getDriverPhone());
            truckInfoVo.setTruckId(truckId);
            truckInfoVo.setTaskStatus(String.valueOf(order.getStatus()));
        }

        KwtWaybillOrderSubtask subtask = kwtWaybillOrderSubtaskRepository.findOneByWOrderNo(Optional.ofNullable(order)
                .map(KwtWaybillOrder::getWOrderNo).
                orElse( null));
        truckInfoVo.setLogicOrderNo(Objects.isNull(subtask) ? "" : String.valueOf(subtask.getLOrderId()));
        if (Objects.isNull(subtask)){
            return truckInfoVo;
        }
        truckInfoVo.setLogicOrderNo(String.valueOf(subtask.getLOrderId()));
        //根据物流订单号查询承运单位 2.代表承运企业
        KwtLogisticsOrderUnit kwtLogisticsOrderUnit = kwtLogisticsOrderUnitRepository.queryByLOrderIdAndUnitType(subtask.getLOrderId(), 2);
        if (Objects.nonNull(kwtLogisticsOrderUnit) && Objects.nonNull(kwtLogisticsOrderUnit.getEntId())){
            EntCacheResDto entCacheResDto = remoteSystemService.queryEntCacheById(kwtLogisticsOrderUnit.getEntId());
            truckInfoVo.setCarrier(Optional.ofNullable(entCacheResDto).map(EntCacheResDto::getFirmName).orElse(""));
        }
        return truckInfoVo;
    }

    private void saveRedisCache(String truckId, String wOrderNo, String truckNo, VehicleReturnData vehicleReturnData) {
        TruckDto truckDto = new TruckDto();
        truckDto.setWOrderNo(vehicleReturnData.getWOrderNo());
        truckDto.setTruckNo(truckNo);
        truckDto.setGpsStatus(String.valueOf(vehicleReturnData.getSpeed()));
        truckDto.setLongitude(vehicleReturnData.getLongitude());
        truckDto.setLatitude(vehicleReturnData.getLatitude());
        if (Objects.nonNull(vehicleReturnData.getTs())){
            LocalDateTime ts = vehicleReturnData.getTs();
            Date date = Date.from(ts.toInstant(ZoneOffset.UTC));
            truckDto.setLocationTime(DateUtils.format(date, DateUtils.DATE_TIME_PATTERN));
        }
        KwtWaybillOrderSubtask subtask = kwtWaybillOrderSubtaskRepository.findOneByWOrderNo(wOrderNo);
        truckDto.setLOrderNo(Objects.nonNull(subtask) ? String.valueOf(subtask.getLOrderId()):"");
        String taskAddress = getTaskAddress(subtask);
        truckDto.setTaskAddress(taskAddress);
        RedissonUtils.putString(CommonConstants.TRUCK_LOCATION + truckId +CommonConstants.UNDERSCORE+ wOrderNo, JSON.toJSONString(truckDto),10,TimeUnit.DAYS);
    }


    public String getTaskAddress(KwtWaybillOrderSubtask subtask) {
        String startPoint = "";
        String endPoint = "";
        if (Objects.nonNull(subtask)){
            List<KwtWaybillOrderAddress> kwtWaybillOrderAddresses = kwtWaybillOrderAddressRepository.queryByWOrderId(subtask.getWOrderId());
            if (CollectionUtils.isNotEmpty(kwtWaybillOrderAddresses)){
                for (KwtWaybillOrderAddress e : kwtWaybillOrderAddresses) {
                    if (Objects.equals(e.getAddressType(), AddressTypeEnum.SHIPMENT.getCode())) {
                        startPoint = e.getDetailAddress();
                    }
                    if (Objects.equals(e.getAddressType(), AddressTypeEnum.TAKE.getCode())) {
                        endPoint = e.getDetailAddress();
                    }
                }
            }
        }
        return startPoint+"-" + endPoint;
    }


    private TruckInfoVo getTruckInfoVoByZj(String truckNo, String wOrderNo,String truckId) {
        CollectZjxlResponse collectZjxlResponse = vehicleCollectService.transTimeManage(truckNo);
        TruckInfoVo instance = TruckInfoVo.getInstance();
        instance.setOrderNo(wOrderNo);
        instance.setTruckNo(truckNo);
        if (Objects.nonNull(collectZjxlResponse) && Objects.nonNull(collectZjxlResponse.getResult()) && Objects.nonNull(collectZjxlResponse.getResult().getFirstVcl())){
            instance.setGpsStatus(collectZjxlResponse.getResult().getFirstVcl().getSpd());
            instance.setLongitude(collectZjxlResponse.getResult().getFirstVcl().getLon());
            instance.setLatitude(collectZjxlResponse.getResult().getFirstVcl().getLat());
            instance.setLocationTime(collectZjxlResponse.getResult().getFirstVcl().getOfflineTime());
        }
        //查询关联订单号

        KwtWaybillOrder oneByTruckNo = kwtWaybillOrderRepository.findOneByTruckNo(truckNo,LoginUserHolder.getEntId());

        KwtWaybillOrderSubtask waybillOrderSubtask = kwtWaybillOrderSubtaskRepository.findOneByWOrderNo(oneByTruckNo.getWOrderNo());
        instance.setLogicOrderNo(Objects.nonNull(waybillOrderSubtask) && Objects.nonNull(waybillOrderSubtask.getLOrderId())
                ? String.valueOf(waybillOrderSubtask.getLOrderId()) : "");
        String taskAddress = getTaskAddress(waybillOrderSubtask);
        instance.setTaskAddress(taskAddress);
        return instance;
    }

    /**
     * 将数据中台的数据进行组织
     * @param truckId 车辆id
     * @param vehicleReturn 中台数据
     * @return 组织的数据
     */
    private TruckInfoVo buildTruckInfo(String truckId, VehicleReturnData vehicleReturn, String truckNo) {
        TruckInfoVo truckInfoVo = TruckInfoVo.getInstance();

        truckInfoVo.setTruckNo(truckNo);
        truckInfoVo.setGpsStatus(String.valueOf(vehicleReturn.getSpeed()));
        truckInfoVo.setLongitude(vehicleReturn.getLongitude());
        truckInfoVo.setLatitude(vehicleReturn.getLatitude());
        truckInfoVo.setLocationTime(Objects.isNull(vehicleReturn.getTs())? "" : DateUtils.format(vehicleReturn.getTs(),DateUtils.DATE_TIME_PATTERN));
        KwtWaybillOrder order = kwtWaybillOrderRepository.findOneByTruckId(truckId);
        if (Objects.nonNull(order)){
            truckInfoVo.setTruckNo(order.getTruckNo());
            truckInfoVo.setOrderNo(order.getWOrderNo());
            truckInfoVo.setDriveId(String.valueOf(order.getDriverId()));
            truckInfoVo.setDriveName(order.getDriverName());
            truckInfoVo.setDrivePhone(order.getDriverPhone());
            truckInfoVo.setTruckId(truckId);
            truckInfoVo.setTaskStatus(String.valueOf(order.getStatus()));
        }

        KwtWaybillOrderSubtask subtask = kwtWaybillOrderSubtaskRepository.findOneByWOrderNo(Optional.ofNullable(order)
                .map(KwtWaybillOrder::getWOrderNo).
                orElse( null));
        truckInfoVo.setLogicOrderNo(Objects.isNull(subtask) ? "" : String.valueOf(subtask.getLOrderId()));
        if (Objects.isNull(subtask)){
            return truckInfoVo;
        }
        //根据物流订单号查询承运单位 2.代表承运企业
        KwtLogisticsOrderUnit kwtLogisticsOrderUnit = kwtLogisticsOrderUnitRepository.queryByLOrderIdAndUnitType(subtask.getLOrderId(), 2);
        if (Objects.nonNull(kwtLogisticsOrderUnit) && Objects.nonNull(kwtLogisticsOrderUnit.getEntId())){
            EntCacheResDto entCacheResDto = remoteSystemService.queryEntCacheById(kwtLogisticsOrderUnit.getEntId());
            truckInfoVo.setCarrier(Optional.ofNullable(entCacheResDto).map(EntCacheResDto::getFirmName).orElse(""));
        }

        List<KwtWaybillOrderAddress> kwtWaybillOrderAddresses = kwtWaybillOrderAddressRepository.queryByWOrderId(subtask.getWOrderId());
        if (CollectionUtils.isEmpty(kwtWaybillOrderAddresses)){
            return truckInfoVo;
        }
        String startPoint = "";
        String endPoint = "";
        for (KwtWaybillOrderAddress kwtWaybillOrderAddress : kwtWaybillOrderAddresses) {
            if (Objects.equals(kwtWaybillOrderAddress.getAddressType(), AddressTypeEnum.SHIPMENT.getCode())) {
                startPoint = kwtWaybillOrderAddress.getDetailAddress();
            }
            if (Objects.equals(kwtWaybillOrderAddress.getAddressType(), AddressTypeEnum.TAKE.getCode())) {
               endPoint = kwtWaybillOrderAddress.getDetailAddress();
            }
        }
        truckInfoVo.setTaskAddress(startPoint+"-"+endPoint);
        return truckInfoVo;
    }

    /**
     * 查询当前任务的轨迹
     * @param req 请求参数
     * @return 响应参数
     */
    public CurrentTaskTraceReqVo queryCurrentTaskTrace(CurrentTaskTraceReq req) {
        log.info("查询当前任务轨迹参数：{}", req);

        Long entId = LoginUserHolder.getEntId();
        String wOrderNo = StringUtils.EMPTY ;
        if (StringUtils.isNotBlank(req.getOrderNo())){
            wOrderNo  = req.getOrderNo();
        }else {
            KwtWaybillOrder waybillOrder = kwtWaybillOrderRepository.findOneByTruckNo(req.getTruckNo(),entId);
            wOrderNo = Optional.ofNullable(waybillOrder).map(KwtWaybillOrder::getWOrderNo).orElse("");
        }
        //查询数据中台获取轨迹
        List<VehicleReturnData> vehicleReturnDataList = getVehicleReturnDataList(wOrderNo);

        CurrentTaskTraceReqVo currentTaskTraceReqVo = new CurrentTaskTraceReqVo();
        if (CollectionUtils.isNotEmpty(vehicleReturnDataList)){
            //组织返回数据
            List<CurrentTaskTraceReqVo.CurrentTaskTrace> currentTaskTraceList = vehicleReturnDataList.stream()
                    .map(kwfTruckTraceService::getCurrentTaskTrace)
                    .filter(x->StringUtils.isNotBlank(x.getLocationTime()))
                    .sorted(Comparator.comparing(CurrentTaskTraceReqVo.CurrentTaskTrace::getLocationTime))
                    .collect(Collectors.toList());

            currentTaskTraceReqVo.setOrderNo(vehicleReturnDataList.get(0).getWOrderNo());

            for (int i = 1; i < currentTaskTraceList.size(); i++) {
                CurrentTaskTraceReqVo.CurrentTaskTrace current = currentTaskTraceList.get(i);
                CurrentTaskTraceReqVo.CurrentTaskTrace previous = currentTaskTraceList.get(i - 1);
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                LocalDateTime currentTime = LocalDateTime.parse(current.getLocationTime(), formatter);
                LocalDateTime previousTime = LocalDateTime.parse(previous.getLocationTime(), formatter);
                Duration duration = Duration.between(previousTime, currentTime);
                current.setDuration(String.valueOf(duration.toMinutes()));
            }
            CurrentTaskTraceReqVo.CurrentTaskTrace first = currentTaskTraceList.get(0);
            CurrentTaskTraceReqVo.CurrentTaskTrace last = currentTaskTraceList.get(currentTaskTraceList.size() - 1);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime firstTime = LocalDateTime.parse(first.getLocationTime(),formatter);
            LocalDateTime lastTime = LocalDateTime.parse(last.getLocationTime(),formatter);

            Duration totalDuration = Duration.between(firstTime, lastTime);
            long durationInMinutes = totalDuration.toMinutes();
            currentTaskTraceReqVo.setTotalDuration(String.valueOf(durationInMinutes));
            currentTaskTraceReqVo.setCurrentTaskTraceList(currentTaskTraceList);
        }

        //构造点位假数据
        List<CurrentTaskTraceReqVo.CurrentAddress> addressList = getCurrentAddresses();
        // 将地址列表设置到 CurrentTaskTraceReqVo 对象中
        currentTaskTraceReqVo.setCurrentAddressList(addressList);
        int sum = addressList.stream()
                .filter(a -> StringUtils.isNotBlank(a.getDuration()))
                .mapToInt(x -> Integer.parseInt(x.getDuration()))
                .sum();
        currentTaskTraceReqVo.setTotalDuration(String.valueOf(sum));
        return currentTaskTraceReqVo;
    }


    private static List<CurrentTaskTraceReqVo.CurrentAddress> getCurrentAddresses() {
        // 创建四条 CurrentAddress 数据
        List<CurrentTaskTraceReqVo.CurrentAddress> addressList = new ArrayList<>();

        // 第一条数据
        CurrentTaskTraceReqVo.CurrentAddress address1 = new CurrentTaskTraceReqVo.CurrentAddress();
        address1.setPoint("金顶集团");
        address1.setDuration("0");
        addressList.add(address1);

        // 第二条数据
        CurrentTaskTraceReqVo.CurrentAddress address2 = new CurrentTaskTraceReqVo.CurrentAddress();
        address2.setPoint("乐山高速路入口");
        address2.setDuration("30");
        addressList.add(address2);

        // 第三条数据
        CurrentTaskTraceReqVo.CurrentAddress address3 = new CurrentTaskTraceReqVo.CurrentAddress();
        address3.setPoint("乐山高速路出口");
        address3.setDuration("50");
        addressList.add(address3);

        // 第四条数据
        CurrentTaskTraceReqVo.CurrentAddress address4 = new CurrentTaskTraceReqVo.CurrentAddress();
        address4.setPoint("乐山大佛加工厂");
        address4.setDuration("60");
        addressList.add(address4);
        addressList = addressList.stream()
                .sorted(Comparator.comparing(CurrentTaskTraceReqVo.CurrentAddress::getDuration))
                .collect(Collectors.toList());
        return addressList;
    }

    /**
     * 查询数据中台获取轨迹
     * @param wOrderNo 运单号
     * @return 轨迹数据
     */
    private List<VehicleReturnData> getVehicleReturnDataList(String wOrderNo) {
        VehicleDataDTO vehicleDataDTO = new VehicleDataDTO();
        vehicleDataDTO.setWOrderNo(wOrderNo);
        String s;
        try {
             s = HttpUtil.postJson(urlConfigProperties.getApiBaseUrl()+ UrlConstants.QUERY_TRACE_URL, JSON.toJSONString(vehicleDataDTO), null);
        } catch (Exception e) {
            log.error("查询任务轨迹异常",e);
            throw new BusinessException("查询任务轨迹异常");
        }
        if (StringUtils.isBlank(s)){
            return Collections.emptyList();
        }
        JSONObject jsonObject = JSON.parseObject(s, JSONObject.class);
        String data = JSON.toJSONString(jsonObject.get("data"));
        return JSON.parseArray(data, VehicleReturnData.class);
    }

    public VehicleReturnData getVehicleReturnData(String truckId) {
        VehicleDataDTO vehicleDataDTO = new VehicleDataDTO();
        vehicleDataDTO.setCarNo(truckId);
        String s = null;
        try {
            s = HttpUtil.postJson(urlConfigProperties.getApiBaseUrl()+ UrlConstants.QUERY_REAL_TIME_TRACE_URL, JSON.toJSONString(vehicleDataDTO), null);
        } catch (Exception e) {
            log.error("查询任务轨迹异常",e);

        }
        if (StringUtils.isBlank(s)){
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(s, JSONObject.class);
        String data = JSON.toJSONString(jsonObject.get("data"));
        return JSON.parseObject(data, VehicleReturnData.class);
    }

    private static CurrentTaskTraceReqVo.CurrentTaskTrace getCurrentTaskTrace(VehicleReturnData e) {
        CurrentTaskTraceReqVo.CurrentTaskTrace currentTaskTrace = new CurrentTaskTraceReqVo.CurrentTaskTrace();
        currentTaskTrace.setLongitude(e.getLongitude());
        currentTaskTrace.setLatitude(e.getLatitude());
        currentTaskTrace.setLocationTime(Objects.isNull(e.getTs()) ? "" : DateUtils.format(e.getTs(), DateUtils.DATE_TIME_PATTERN));
        return currentTaskTrace;
    }

    /**
     * 查询车辆轨迹
     * @param req 轨迹参数
     * @return 轨迹数据
     */
    public CurrentTaskTraceReqVo queryCurrentTruckTrace(CurrentTaskTraceReq req) {
        log.info("查询车辆轨迹参数：{}", req);
        if (StringUtils.isBlank(req.getTruckNo())){
            throw  new BusinessException("车牌号不能为空");
        }
        //cxf todo 查询车辆td数据库

        return new CurrentTaskTraceReqVo();
    }

    /**
     * 上报车辆轨迹
     * @param req 请求参数
     * @return 响应参数
     */
    public Void vehiclesTrajectory( VehiclesTrajectoryReq req) {
        //通过手机号查询司机以及车辆信息
        //req.setTs(DateUtils.format(new Date(),DateUtils.DATE_TIME_PATTERN));
        RDriverVo rDriverVo = fleetService.findDriverByPhone(req.getMobile());
        if (Objects.isNull(rDriverVo)){
            throw new BusinessException("司机信息不存在");
        }
        initReq(req);
        //查询认为中的运单信息
        KwtWaybillOrder waybillOrder = kwtWaybillOrderRepository.findOneByDriverId(rDriverVo.getId());
        //获取车队信息
        RFleetDriverVo fleetByDriveId = fleetService.findFleetByDriveId(rDriverVo.getId());
        req.setLOrderNo(Optional.ofNullable(waybillOrder)
                .map(KwtWaybillOrder::getWOrderNo).orElse(""));
        req.setWOrderNo(Optional.ofNullable(waybillOrder)
                .map(KwtWaybillOrder::getWOrderNo).orElse(""));
        VehiclesTrajectoryReq.VehicleDataVO vehicleDataVO = new VehiclesTrajectoryReq.VehicleDataVO();
        //车牌id     cxf todo 车牌号写死
        Long truckId = Optional.ofNullable(waybillOrder)
                .map(KwtWaybillOrder::getTruckId)
                .orElse(195160604170784768L);

        req.setTruckNo(String.valueOf(truckId));
        vehicleDataVO.setCarNo(String.valueOf(truckId));

        vehicleDataVO.setFleetId(String.valueOf(Optional.ofNullable(fleetByDriveId)
                .map(RFleetDriverVo::getFleetId)
                .orElse(null)));
        req.setVehicleDataVO(vehicleDataVO);
        req.setStatus("1");
        try {
            String url = urlConfigProperties.getApiBaseUrl();
            HttpUtil.postJson(url+ UrlConstants.VEHICLE_TRAJECTORY, JSON.toJSONString(req), null);
        } catch (Exception e) {
            log.error("app上报车辆轨迹异常",e);
            throw new BusinessException("app上报车辆轨迹异常");
        }
        String key = CommonConstants.TRUCK_LOCATION + truckId+CommonConstants.UNDERSCORE;
        String xwOrderNo = "";
        if (Objects.nonNull(waybillOrder)){
            xwOrderNo = waybillOrder.getWOrderNo();
            key = CommonConstants.TRUCK_LOCATION + truckId+CommonConstants.UNDERSCORE+xwOrderNo;
        }
        //先删除缓存
        RedissonUtils.delete(key);
        //组织缓存数据
        TruckDto truckDto = getTruckDto(req,xwOrderNo);
        //放入缓存  存十天
        RedissonUtils.putString(key,JSON.toJSONString(truckDto),10, TimeUnit.DAYS);
        return null;
    }

    private void initReq(VehiclesTrajectoryReq req) {
        req.setGpsStatus(req.getStatus());
        req.setDirection(30.0f);
        req.setFuelLevel(30.0f);
        req.setMileage("1.0");
        req.setEngineTemp(25.0f);
        req.setBatteryVoltage(12.0f);
        req.setStatus("1");
        req.setAlarmCode("123");
    }

    /**
     * 组织返回数据
     * @param req 请求参数
     * @return 缓存数据
     */
    private TruckDto getTruckDto(VehiclesTrajectoryReq req,String wOrderNo) {
        TruckDto truckDto = new TruckDto();
        truckDto.setWOrderNo(wOrderNo);
        truckDto.setTruckNo(req.getTruckNo());
        truckDto.setGpsStatus(String.valueOf(req.getSpeed()));
        truckDto.setLongitude(req.getLongitude());
        truckDto.setLatitude(req.getLatitude());
        truckDto.setLocationTime(DateUtils.format(LocalDateTime.now(), DateUtils.DATE_TIME_PATTERN));
        truckDto.setLOrderNo(req.getLOrderNo());
        KwtWaybillOrderSubtask subtask = kwtWaybillOrderSubtaskRepository.findOneByWOrderNo(wOrderNo);
        String taskAddress = getTaskAddress(subtask);
        truckDto.setTaskAddress(taskAddress);
        return truckDto;
    }
}
