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

import com.clx.performance.esplus.mapper.DriverTraceESPlusMapper;
import com.clx.performance.esplus.mapper.TruckTraceESPlusMapper;
import com.clx.performance.esplus.model.DriverTraceESPlus;
import com.clx.performance.esplus.model.TruckTraceESPlus;
import com.clx.performance.param.temp.DriverTraceAddParam;
import com.clx.performance.param.temp.TruckTraceAddParam;
import com.clx.performance.service.trace.TruckTraceService;
import com.clx.performance.struct.trace.DriverTraceStruct;
import com.clx.performance.struct.trace.TruckTraceStruct;
import com.clx.performance.utils.LocalDateTimeUtils;
import com.clx.performance.vo.pc.trace.DriverTraceVO;
import com.clx.performance.vo.pc.trace.DriverTruckTraceVO;
import lombok.extern.slf4j.Slf4j;
import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class TruckTraceServiceImpl implements TruckTraceService {
    // 停留速度
    private static final Integer PARK_SPEED = 5;

    @Autowired
    private TruckTraceESPlusMapper truckTraceESPlusMapper;
    @Autowired
    private DriverTraceESPlusMapper driverTraceESPlusMapper;

    @Autowired
    private TruckTraceStruct truckTraceStruct;
    @Autowired
    private DriverTraceStruct driverTraceStruct;

    @Override
    public List<DriverTruckTraceVO> listTruckTraceByTime(String truckNo, String beginTime, String endTime) {
        List<TruckTraceESPlus> list = truckTraceESPlusMapper.selectList(new LambdaEsQueryWrapper<TruckTraceESPlus>()
                .eq(TruckTraceESPlus::getTruckNo, truckNo)
                .ge(TruckTraceESPlus::getGpsTime, beginTime)
                .le(TruckTraceESPlus::getGpsTime, endTime)
                .orderByAsc("gpsTime")
        );

        List<DriverTruckTraceVO> traceList = truckTraceStruct.convert(list);

        // 停留时长计算
        Integer parkIdx = null;
        for (int i=0; i<traceList.size(); i++){
            if (traceList.get(i).getSpeed() == null){continue;}

            if (traceList.get(i).getSpeed().compareTo(new BigDecimal(PARK_SPEED)) < 0){
                if (parkIdx == null) {parkIdx = i;}
            }
            else {
                if (parkIdx == null) {continue;}
                long stayTime = Duration.between(LocalDateTimeUtils.parseTime(traceList.get(parkIdx).getGpsTime()), LocalDateTimeUtils.parseTime(traceList.get(i).getGpsTime())).getSeconds();
                traceList.get(parkIdx).setStayTime(new BigDecimal(stayTime).divide(new BigDecimal(60), 1, RoundingMode.HALF_UP));
                parkIdx = null;
            }
        }

        if (parkIdx!=null && parkIdx < traceList.size()-1){
            long stayTime = Duration.between(LocalDateTimeUtils.parseTime(traceList.get(parkIdx).getGpsTime()), LocalDateTimeUtils.parseTime(traceList.get(traceList.size()-1).getGpsTime())).getSeconds();
            traceList.get(parkIdx).setStayTime(new BigDecimal(stayTime).divide(new BigDecimal(60), 1, RoundingMode.HALF_UP));
        }

        return traceList;
    }

    @Override
    public List<DriverTraceVO> listDriverTraceByTime(Long userNo, String beginTime, String endTime) {
        List<DriverTraceESPlus> list = driverTraceESPlusMapper.selectList(new LambdaEsQueryWrapper<DriverTraceESPlus>()
                .eq(DriverTraceESPlus::getUserNo, userNo)
                .ge(DriverTraceESPlus::getPositionTime, beginTime)
                .le(DriverTraceESPlus::getPositionTime, endTime)
                .orderByAsc("positionTime")
        );

        List<DriverTraceVO> traceList = driverTraceStruct.convert(list);

        // 停留时长计算
        Integer parkIdx = null;
        for (int i=0; i<traceList.size(); i++){
            if (traceList.get(i).getSpeed() == null){continue;}

            if (traceList.get(i).getSpeed().compareTo(new BigDecimal(PARK_SPEED)) < 0){
                if (parkIdx == null) {parkIdx = i;}
            }
            else {
                if (parkIdx == null) {continue;}
                long stayTime = Duration.between(LocalDateTimeUtils.parseTime(traceList.get(parkIdx).getGpsTime()), LocalDateTimeUtils.parseTime(traceList.get(i).getGpsTime())).getSeconds();
                traceList.get(parkIdx).setStayTime(new BigDecimal(stayTime).divide(new BigDecimal(60), 1, RoundingMode.HALF_UP));
                parkIdx = null;
            }
        }

        if (parkIdx!=null && parkIdx < traceList.size()-1){
            long stayTime = Duration.between(LocalDateTimeUtils.parseTime(traceList.get(parkIdx).getGpsTime()), LocalDateTimeUtils.parseTime(traceList.get(traceList.size()-1).getGpsTime())).getSeconds();
            traceList.get(parkIdx).setStayTime(new BigDecimal(stayTime).divide(new BigDecimal(60), 1, RoundingMode.HALF_UP));
        }

        return traceList;
    }

    @Override
    public void truckTraceSave(TruckTraceAddParam param){

        List<TruckTraceESPlus> list = new ArrayList<>();
        for (TruckTraceAddParam.TruckTraceItem item : param.getTraceList()) {
            TruckTraceESPlus es = new TruckTraceESPlus();
            es.setTruckNo(item.getTruckNo());
            es.setAngle(item.getAngle());
            es.setHeight(item.getHeight());
            es.setLocation(item.getLocation());
            es.setGpsTime(item.getGpsTime());
            es.setMileage(item.getMileage());
            es.setSpeed(item.getSpeed());
            es.setCreateTime(LocalDateTimeUtils.formatTime());

            list.add(es);
        }

        truckTraceESPlusMapper.insertBatch(list);
    }
    @Override
    public void driverTraceSave(DriverTraceAddParam param){

        List<DriverTraceESPlus> list = new ArrayList<>();
        for (DriverTraceAddParam.DriverTraceItem item : param.getTraceList()) {
            DriverTraceESPlus es = new DriverTraceESPlus();
            es.setUserNo(item.getUserNo());
            es.setDataType(item.getDataType());
            es.setLocation(item.getLocation());
            es.setPositionTime(item.getGpsTime());
            es.setCreateTime(LocalDateTimeUtils.formatTime());
            es.setModifiedTime(es.getCreateTime());

            list.add(es);
        }

        driverTraceESPlusMapper.insertBatch(list);
    }

    @Override
    public BigDecimal[] getCurrentPosition(String truckNo, Long userNo) {
        String beginTime = LocalDateTimeUtils.formatTime(LocalDateTime.now().minusMinutes(5));
        String endTime = LocalDateTimeUtils.formatTime();

        // 车辆
        List<TruckTraceESPlus> list = truckTraceESPlusMapper.selectList(new LambdaEsQueryWrapper<TruckTraceESPlus>()
                .eq(TruckTraceESPlus::getTruckNo, truckNo)
                .ge(TruckTraceESPlus::getGpsTime, beginTime)
                .le(TruckTraceESPlus::getGpsTime, endTime)
                .orderByDesc("gpsTime")
                .limit(1)
        );
        if (!list.isEmpty()){
            return list.get(0).getLocation();
        }

        // 司机
        List<DriverTraceESPlus> list1 = driverTraceESPlusMapper.selectList(new LambdaEsQueryWrapper<DriverTraceESPlus>()
                .eq(DriverTraceESPlus::getUserNo, userNo)
                .ge(DriverTraceESPlus::getPositionTime, beginTime)
                .le(DriverTraceESPlus::getPositionTime, endTime)
                .orderByDesc("positionTime")
                .limit(1)
        );
        if (!list1.isEmpty()){
            return list1.get(0).getLocation();
        }

        return null;
    }

    @Override
    public int getParkTime(String truckNo, Long userNo) {
        String beginTime = LocalDateTimeUtils.formatTime(LocalDateTime.now().minusDays(1));
        String endTime = LocalDateTimeUtils.formatTime();

        // 车辆
        List<TruckTraceESPlus> list = truckTraceESPlusMapper.selectList(new LambdaEsQueryWrapper<TruckTraceESPlus>()
                .eq(TruckTraceESPlus::getTruckNo, truckNo)
                .gt(TruckTraceESPlus::getSpeed, PARK_SPEED)
                .ge(TruckTraceESPlus::getGpsTime, beginTime)
                .le(TruckTraceESPlus::getGpsTime, endTime)
                .orderByAsc("gpsTime")
                .limit(1)
        );
        if (!list.isEmpty()){
            list = truckTraceESPlusMapper.selectList(new LambdaEsQueryWrapper<TruckTraceESPlus>()
                    .eq(TruckTraceESPlus::getTruckNo, truckNo)
                    .gt(TruckTraceESPlus::getSpeed, PARK_SPEED)
                    .gt(TruckTraceESPlus::getGpsTime, list.get(0).getGpsTime())
                    .le(TruckTraceESPlus::getGpsTime, endTime)
                    .orderByDesc("gpsTime")
            );
            return (int)Duration.between(LocalDateTimeUtils.parseTime(list.get(0).getGpsTime()), LocalDateTimeUtils.parseTime(list.get(list.size() - 1).getGpsTime())).toMinutes();

        }

        // 司机
        List<DriverTraceESPlus> list1 = driverTraceESPlusMapper.selectList(new LambdaEsQueryWrapper<DriverTraceESPlus>()
                .eq(DriverTraceESPlus::getUserNo, userNo)
                .ge(DriverTraceESPlus::getPositionTime, beginTime)
                .le(DriverTraceESPlus::getPositionTime, endTime)
                .orderByAsc("positionTime")
                .limit(1)
        );
        if (!list1.isEmpty()){
            list1 = driverTraceESPlusMapper.selectList(new LambdaEsQueryWrapper<DriverTraceESPlus>()
                    .eq(DriverTraceESPlus::getUserNo, userNo)
                    .eq(DriverTraceESPlus::getSpeed, PARK_SPEED)
                    .ge(DriverTraceESPlus::getPositionTime, list1.get(0).getPositionTime())
                    .le(DriverTraceESPlus::getPositionTime, endTime)
                    .orderByDesc("positionTime")
            );
            return (int)Duration.between(LocalDateTimeUtils.parseTime(list1.get(0).getPositionTime()), LocalDateTimeUtils.parseTime(list1.get(list1.size() - 1).getPositionTime())).toMinutes();
        }

        return 0;
    }

}
