package com.clx.performance.service.impl.trace;

import com.alibaba.fastjson.JSON;
import com.clx.order.enums.ResultEnum;
import com.clx.performance.dao.OrderChildDao;
import com.clx.performance.enums.DriverTruckEnum;
import com.clx.performance.model.OrderChild;
import com.clx.performance.param.pc.trace.QueryTraceParam;
import com.clx.performance.service.trace.TraceMonitorService;
import com.clx.performance.service.trace.TruckTraceService;
import com.clx.performance.utils.LocalDateTimeUtils;
import com.clx.performance.vo.pc.trace.DriverTraceVO;
import com.clx.performance.vo.pc.trace.DriverTruckTraceVO;
import com.clx.performance.vo.pc.trace.OrderChildTraceVO;
import com.msl.common.exception.ServiceSystemException;
import com.msl.common.utils.DateUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
@AllArgsConstructor
public class TraceMonitorServiceImpl implements TraceMonitorService {

    private final TruckTraceService truckTraceService;
    private final OrderChildDao orderChildDao;
    //private final TruckFeign truckFeign;

    private final int TRACE_DAY_MAX = 7;

    private final static long stopMinutes = 5;
    @Override
    public OrderChildTraceVO getOrderChildTrace(QueryTraceParam param) {
        if(StringUtils.isBlank(param.getChildNo())){
            throw new ServiceSystemException(ResultEnum.PARAM_ERROR,"运单编号不能为空");
        }
        checkParam(param);
        OrderChild child = orderChildDao.getByChildNo(param.getChildNo()).orElseThrow(ResultEnum.DATA_NOT_FIND,
                "运单数据不存在");
        List<DriverTruckTraceVO> truckTrace = truckTraceService.listTruckTraceByTime(param.getTruckNo(),param.getBeginTime(),param.getEndTime());
        // 接单重车、卸车空车
        for (DriverTruckTraceVO item : truckTrace) {
            item.setTruckStatus(DriverTruckEnum.TraceTruckStatus.HEAVY.getCode());
            if (child.getCancelTime() != null){
                if (LocalDateTimeUtils.parseTime(item.getGpsTime()).isAfter(child.getCancelTime())){
                    item.setTruckStatus(DriverTruckEnum.TraceTruckStatus.EMPTY.getCode());}
            }
            if (child.getUnloadTime() != null){
                if (LocalDateTimeUtils.parseTime(item.getGpsTime()).isAfter(child.getUnloadTime())){
                    item.setTruckStatus(DriverTruckEnum.TraceTruckStatus.EMPTY.getCode());}
            }
        }
        List<DriverTraceVO> driverTrace = truckTraceService.listDriverTraceByTime(child.getDriverUserNo(),param.getBeginTime(),param.getEndTime());

        OrderChildTraceVO result = new OrderChildTraceVO();
        result.setDriverTraceList(splitDriverTrace(driverTrace));
        result.setTruckTraceList(splitTruckTrace(truckTrace));
        return result;
    }

    @Override
    public OrderChildTraceVO getTruckTrace(QueryTraceParam param) {
        checkParam(param);
        //查询车辆的车主信息
/*        Result<TruckOwnerInfoVO> result = truckFeign.getTruckOwnerInfo(
                param.getTruckNo());
        log.info("查询车辆车主信息,车牌号:{},结果:{}",param.getTruckNo(),result);
        if(!result.succeed() || Objects.isNull(result.getData())){
            throw new ServiceSystemException(ResultEnum.DATA_NOT_FIND,"未查询到车辆车主信息");
        }
        long userNo = result.getData().getUserNo();*/

        return this.getTrace(null,param.getTruckNo(),param.getBeginTime(),param.getEndTime());
    }


    private OrderChildTraceVO getTrace(Long userNo,String truckNo,String beginTime,String endTime){
        OrderChildTraceVO result = new OrderChildTraceVO();
        List<DriverTruckTraceVO> truckTrace = truckTraceService.listTruckTraceByTime(truckNo,beginTime,endTime);
        if(Objects.nonNull(userNo)){
            List<DriverTraceVO> driverTrace = truckTraceService.listDriverTraceByTime(userNo,beginTime,endTime);
            result.setDriverTraceList(splitDriverTrace(driverTrace));
        }
        result.setTruckTraceList(splitTruckTrace(truckTrace));
        return result;
    }
    //如果停留时间超过指定时间，则切分轨迹信息为多段
    public static List<List<DriverTruckTraceVO>> splitTruckTrace(List<DriverTruckTraceVO> traceList){
        List<List<DriverTruckTraceVO>> result = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(traceList)){
            if(traceList.size() == 1){
                result.add(traceList);
                return result;
            }else{
                List<DriverTruckTraceVO> temp = new ArrayList<>();
                temp.add(traceList.get(0));
                for(int i = 1; i< traceList.size(); i ++){
                    DriverTruckTraceVO current = traceList.get(i);
                    DriverTruckTraceVO prev = traceList.get(i-1);
                    long minutes = LocalDateTimeUtils.betweenMin(DateUtils.parseDateTime(prev.getGpsTime()).get(),
                            DateUtils.parseDateTime(current.getGpsTime()).get());
                    //如果两个坐标停留的时间超过指定时间，则为新的一段路线。
                    if(minutes > stopMinutes){
                        result.add(temp);
                        temp = new ArrayList<>();
                        temp.add(current);
                    }else{
                        temp.add(current);
                    }
                }
                result.add(temp);
            }
        }
        return result;
    }

    //如果停留时间超过指定时间，则切分轨迹信息为多段
    public static List<List<DriverTraceVO>> splitDriverTrace(List<DriverTraceVO> driverTraceList){
        List<List<DriverTraceVO>> result = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(driverTraceList)){
            if(driverTraceList.size() == 1){
                result.add(driverTraceList);
                return result;
            }else{
                List<DriverTraceVO> temp = new ArrayList<>();
                temp.add(driverTraceList.get(0));
                for(int i = 1; i< driverTraceList.size(); i ++){
                    DriverTraceVO current = driverTraceList.get(i);
                    DriverTraceVO prev = driverTraceList.get(i-1);
                    long minutes = LocalDateTimeUtils.betweenMin(DateUtils.parseDateTime(prev.getGpsTime()).get(),
                            DateUtils.parseDateTime(current.getGpsTime()).get());
                    //如果两个坐标停留的时间超过指定时间，则为新的一段路线。
                    if(minutes > stopMinutes){
                        result.add(temp);
                        temp = new ArrayList<>();
                        temp.add(current);
                    }else{
                        temp.add(current);
                    }
                }
                result.add(temp);
            }
        }
        return result;
    }


    public static void main(String[] args) {
        List<DriverTruckTraceVO> traceList  = new ArrayList<>();
        int minStart =10;
        for (int i = 0; i < 20; i++) {
            DriverTruckTraceVO v1 = new DriverTruckTraceVO();
            if(i == 10){
                minStart  = minStart + 6;
                v1.setGpsTime("2021-01-01 10:"+minStart+":00");

            }else if(i == 13){
                minStart  = minStart + 8;
                v1.setGpsTime("2021-01-01 10:"+minStart+":00");

            }else if(i == 19){
                minStart  = minStart + 7;
                v1.setGpsTime("2021-01-01 10:"+minStart+":00");

            }else{
                minStart  = minStart + 1;
                v1.setGpsTime("2021-01-01 10:"+minStart+":00");
            }
            traceList.add(v1);
        }

        List<List<DriverTruckTraceVO>> lists = splitTruckTrace(traceList);

        for(List<DriverTruckTraceVO> item : lists){
            System.out.println(JSON.toJSONString(item));
        }
    }







    public void checkParam(QueryTraceParam param){
        LocalDateTime beginTime = DateUtils.parseDateTime(param.getBeginTime()).get();
        LocalDateTime endTime = DateUtils.parseDateTime(param.getEndTime()).get();
        if (endTime.isAfter(beginTime.plusDays(TRACE_DAY_MAX)) ) {      //最多查询7天
            throw new ServiceSystemException(ResultEnum.PARAM_ERROR,"选择的时间范围需小于7天");
        }
    }
}
