package com.gci.boot.modules.statis.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Segment;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gci.boot.common.util.DateUtils;
import com.gci.boot.modules.basedata.entity.TbVehicle;
import com.gci.boot.modules.basedata.service.ITbVehicleService;
import com.gci.boot.modules.driver.entity.TbDriver;
import com.gci.boot.modules.driver.mapper.TbDriverSignInMapper;
import com.gci.boot.modules.driver.vo.DriverWorkVO;
import com.gci.boot.modules.gis.entity.TbGisActiveSafetyAlarm;
import com.gci.boot.modules.gis.entity.TbGisFenceAlarm;
import com.gci.boot.modules.gis.entity.TbGisGps;
import com.gci.boot.modules.gis.entity.TbGisSpeedingAlarm;
import com.gci.boot.modules.gis.service.*;
import com.gci.boot.modules.gis.vo.VehicleWorkVO;
import com.gci.boot.modules.projects.service.IProjectsService;
import com.gci.boot.modules.statis.service.VehicleStatisService;
import com.gci.boot.modules.statis.vo.*;
import com.gci.boot.modules.vehicles.entity.TbAccidentInfo;
import com.gci.boot.modules.vehicles.entity.TbViolationRecord;
import com.gci.boot.modules.vehicles.mapper.*;
import com.gci.boot.modules.vehicles.service.ITbAccidentInfoService;
import com.gci.boot.modules.vehicles.service.ITbViolationRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Slf4j
public class VehicleStatisServiceImpl implements VehicleStatisService {
    @Autowired
    private TbRepairInfoMapper repairInfoMapper;
    @Autowired
    private TbUpkeepBillMapper upkeepBillMapper;
    @Autowired
    private TbInsuranceMapper insuranceMapper;
    @Autowired
    private TbAnnualInspectionInfoMapper annualInspectionInfoMapper;

    @Autowired
    private IGisGpsAnalysisService iGisGpsAnalysisService;

    @Autowired
    private ITbAccidentInfoService iTbAccidentInfoService;

    @Autowired
    private ITbViolationRecordService iTbViolationRecordService;
    @Autowired
    private ITbGisSpeedingAlarmService iTbGisSpeedingAlarmService;
    @Autowired
    private ITbGisFenceAlarmService iTbGisFenceAlarmService;
    @Autowired
    private ITbGisActiveSafetyAlarmService iTbGisActiveSafetyAlarmService;
    @Autowired
    private ITbGisGpsService iTbGisGpsService;
    @Autowired
    private TbViolationRecordMapper violationRecordMapper;
    @Autowired
    private ITbVehicleService vehicleService;

    @Autowired
    private TbDriverSignInMapper driverSignInMapper;
    @Autowired
    private IProjectsService projectsService;

    @Override
    public IPage<VehicleStatisVo> page(Page<VehicleStatisVo> page, StatisParamVO vo) {
        List<VehicleStatisVo> vehicleStatisVos = getVehicleStatisVos(vo);
        if (vehicleStatisVos.size() == 0) {
            return page;
        }
        PageUtil.setOneAsFirstPageNo();
        int totalPage = PageUtil.totalPage(vehicleStatisVos.size(), Convert.toInt(page.getSize()));
        if (page.getCurrent() > totalPage) {
            page.setCurrent(totalPage);
        }
        page.setTotal(vehicleStatisVos.size());
        page.setPages(totalPage);
        Segment<Integer> integerSegment = PageUtil.toSegment(Convert.toInt(page.getCurrent()), Convert.toInt(page.getSize()));
        Integer endIndex = integerSegment.getEndIndex();
        if (endIndex > vehicleStatisVos.size()) {
            endIndex = vehicleStatisVos.size();
        }
        page.setRecords(vehicleStatisVos.subList(integerSegment.getStartIndex(), endIndex));
        return page;
    }

    private Map<String, VehicleStatisVo> getVehicleTraffic(StatisParamVO vo) {
        List<RepairStatisVO> repairList = repairInfoMapper.findStatisRepairAndPlateNumberAll(vo,new ArrayList<>());
        List<UpkeepStatisVO> upkeepList = upkeepBillMapper.findStatisUpkeepAndPlateNumberAll(vo,new ArrayList<>());
        List<InsuranceStatisVo> insuranceList = insuranceMapper.findStatisInsuranceAndPlateNumberAll(vo,new ArrayList<>());
        List<AnnualInspectionInfoStatisVo> annualInspectionInfoList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoAndPlateNumberAll(vo,new ArrayList<>());

        Map<String, VehicleStatisVo> vehicleStatisMap = new HashMap<>();

        for (RepairStatisVO to : repairList) {
            String key = to.getPlateNumber();
            //如果Map中已经存在该键，说明已经有一个ReportListVo对象，那么只需要更新其维修统计字段
            if (vehicleStatisMap.containsKey(key)) {
                VehicleStatisVo rl = vehicleStatisMap.get(key);
                rl.setRepairAmount(rl.getRepairAmount() + to.getRepairAmount());
                rl.setRepairNum(rl.getRepairNum() + to.getRepairTimes());
            } else {
                //否则，创建一个新的ReportListVo对象，并设置其项目Id，项目名称，车辆类型和维修统计字段
                VehicleStatisVo rl = new VehicleStatisVo();
                rl.setRepairNum(to.getRepairTimes().longValue());
                rl.setRepairAmount(to.getRepairAmount());
                rl.setPlateNumber(to.getPlateNumber());
                //将新的ReportListVo对象放入Map中
                vehicleStatisMap.put(key, rl);
            }
        }
        for (UpkeepStatisVO to : upkeepList) {
            String key = to.getPlateNumber();
            //如果Map中已经存在该键，说明已经有一个ReportListVo对象，那么只需要更新其维修统计字段
            if (vehicleStatisMap.containsKey(key)) {
                VehicleStatisVo rl = vehicleStatisMap.get(key);
                rl.setUpkeepAmount(rl.getUpkeepAmount() + to.getUpkeepAmount());
            } else {
                //否则，创建一个新的ReportListVo对象，并设置其项目Id，项目名称，车辆类型和维修统计字段
                VehicleStatisVo rl = new VehicleStatisVo();
                rl.setPlateNumber(to.getPlateNumber());
                rl.setUpkeepAmount(to.getUpkeepAmount());
                //将新的ReportListVo对象放入Map中
                vehicleStatisMap.put(key, rl);
            }
        }
        for (InsuranceStatisVo to : insuranceList) {
            String key = to.getPlateNumber();
            //如果Map中已经存在该键，说明已经有一个ReportListVo对象，那么只需要更新其维修统计字段
            if (vehicleStatisMap.containsKey(key)) {
                VehicleStatisVo rl = vehicleStatisMap.get(key);
                rl.setInsuranceAmount(rl.getInsuranceAmount() + to.getTotalPrice());
            } else {
                //否则，创建一个新的ReportListVo对象，并设置其项目Id，项目名称，车辆类型和维修统计字段
                VehicleStatisVo rl = new VehicleStatisVo();
                rl.setPlateNumber(to.getPlateNumber());
                rl.setInsuranceAmount(to.getTotalPrice());
                //将新的ReportListVo对象放入Map中
                vehicleStatisMap.put(key, rl);
            }
        }
        for (AnnualInspectionInfoStatisVo to : annualInspectionInfoList) {
            String key = to.getPlateNumber();
            //如果Map中已经存在该键，说明已经有一个ReportListVo对象，那么只需要更新其维修统计字段
            if (vehicleStatisMap.containsKey(key)) {
                VehicleStatisVo rl = vehicleStatisMap.get(key);
                rl.setInspectionAmount(rl.getInspectionAmount() + to.getInspectionAmount());
            } else {
                //否则，创建一个新的ReportListVo对象，并设置其项目Id，项目名称，车辆类型和维修统计字段
                VehicleStatisVo rl = new VehicleStatisVo();
                rl.setPlateNumber(to.getPlateNumber());
                rl.setInspectionAmount(to.getInspectionAmount());
                //将新的ReportListVo对象放入Map中
                vehicleStatisMap.put(key, rl);
            }
        }
        return vehicleStatisMap;
    }

    private List<VehicleStatisVo> getVehicleStatisVos(StatisParamVO vo) {

        vo.setStatisTime("YYYY");

        //用户关联项目
        List<String> listProjectIds = projectsService.queryAllProjectListOfUser();

        //车辆基础信息
        List<TbVehicle> list = vehicleService.list(new LambdaQueryWrapper<TbVehicle>()
        .like(StrUtil.isNotBlank(vo.getPlateNumber()),TbVehicle::getPlateNumber,vo.getPlateNumber())
        .like(StrUtil.isNotBlank(vo.getFrameNumber()),TbVehicle::getFrameNumber,vo.getFrameNumber()));

        List<RepairStatisVO> repairList = repairInfoMapper.findStatisRepairAndPlateNumberAllHis(vo,listProjectIds);
        List<UpkeepStatisVO> upkeepList = upkeepBillMapper.findStatisUpkeepAndPlateNumberAllHis(vo,listProjectIds);
        List<InsuranceStatisVo> insuranceList = insuranceMapper.findStatisInsuranceAndPlateNumberAllHis(vo,listProjectIds);
        List<AnnualInspectionInfoStatisVo> annualInspectionInfoList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoAndPlateNumberAllHis(vo,listProjectIds);
        List<ViolationRecordStatisVO> violationList = violationRecordMapper.findStatisViolationAndPlateNumberAllHis(vo, listProjectIds);

        Map<String, VehicleStatisVo> map = getStringVehicleStatisVoMap(vo,list,repairList, upkeepList, insuranceList, annualInspectionInfoList,violationList);
        ArrayList<VehicleStatisVo> vehicleStatisVos = new ArrayList<>(map.values());
        if (!vehicleStatisVos.isEmpty()) {
            vehicleStatisVos.sort(Comparator.comparing(VehicleStatisVo::getStatisTime));
        }
        return vehicleStatisVos;
    }

    @Override
    public List<VehicleStatisVo> getAll(StatisParamVO vo) {
        return getVehicleStatisVos(vo);
    }

    @Override
    public List<VehicleAnalysisVO> analysisVehicleByListAndTime(List<TbVehicle> vehicles, Date startTime, Date endTime) {
        List<String> plates = vehicles.stream().map(v -> v.getPlateNumber()).collect(Collectors.toList());
        List<VehicleWorkVO> workVOList = iGisGpsAnalysisService.findAnalysisByTimeAndVehicle(plates, startTime, endTime);

        Map<String, VehicleWorkVO> groupBy = workVOList.stream().collect(Collectors.toMap(VehicleWorkVO::getNumberPlate, vehicleWorkVO -> vehicleWorkVO));
        StatisParamVO queryVO = new StatisParamVO();
        queryVO.setPlates(plates);
        queryVO.setStatisTime("yyyy-MM-dd");
        queryVO.setStartTime(DateUtils.formatTime(startTime));
        queryVO.setEndTime(DateUtils.formatTime(endTime));

        Map<String, VehicleStatisVo> groupByTraffic = getVehicleTraffic(queryVO);

        List<VehicleAnalysisVO> analysisVOS = vehicles.stream().map(a -> {
            VehicleAnalysisVO vo = new VehicleAnalysisVO();
            VehicleWorkVO work = groupBy.getOrDefault(a.getPlateNumber(), new VehicleWorkVO());
            VehicleStatisVo traffic = groupByTraffic.getOrDefault(a.getPlateNumber(), new VehicleStatisVo());
            BeanUtils.copyProperties(a, vo);
            vo.setCost(a.getPrice().toString());
            vo.setAge(String.valueOf(DateUtil.betweenYear(vo.getDeliveryTime(), new Date(), false)));
            vo.setResidualValue("0");
            vo.setRentalIncome("0");

            vo.setDriverMile(work.getDriverMile());
            vo.setDriverHour(work.getDriverHour());
            vo.setWorkMile(work.getWorkMile());
            vo.setWorkHour(work.getWorkHour());

            vo.setRepairNum(traffic.getRepairNum().toString());
            vo.setRepairFee(traffic.getRepairAmount().toString());
            vo.setInsuranceFee(traffic.getInsuranceAmount().toString());
            vo.setAnnualFee(traffic.getInspectionAmount().toString());
            vo.setUpkeepFee(traffic.getUpkeepAmount().toString());

            return vo;
        }).collect(Collectors.toList());
        return analysisVOS;
    }

    @Override
    public List<DriverAnalysisVO> analysisDriverByListAndTime(List<TbDriver> drivers, String startTime, String endTime) {
        //得到要查询的司机id信息
        List<String> driverIds = drivers.stream().map(v -> v.getId()).collect(Collectors.toList());
        if(driverIds.isEmpty()){
            return new ArrayList<>();
        }
        List<DriverWorkVO> driverWorkVOS = new ArrayList<>();
        //得到统计时段 司机上下班的信息
        try {
            driverWorkVOS = driverSignInMapper.findWorkByList(driverIds, DateUtils.parseDate(startTime, "yyyy-MM-dd HH:mm:ss"), DateUtils.parseDate(endTime, "yyyy-MM-dd HH:mm:ss"));
        } catch (ParseException e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
        //根据司机进行司机作业信息分组
        Map<String, List<DriverWorkVO>> groupByDriver = driverWorkVOS.stream().collect(Collectors.groupingBy(DriverWorkVO::getDriverId));
        List<DriverAnalysisVO> analysisVOS = drivers.parallelStream().map(a -> {
            DriverAnalysisVO vo = new DriverAnalysisVO();
            BeanUtils.copyProperties(a, vo);
            List<DriverWorkVO> workList = groupByDriver.getOrDefault(a.getId(),new ArrayList<>());
            //去重统计时段里司机驾驶的车辆种类
            String vehicleType = workList.stream().map(w -> w.getVehicleType()).distinct().collect(Collectors.joining(","));
            vo.setVehicleType(vehicleType);

            //去重统计时段里司机的车辆信息
            List<String> plateNumberByDriver = workList.stream().map(w -> w.getPlateNumber()).distinct().collect(Collectors.toList());

            //根据司机的车辆及工作时段统计各类数据。
            String accidentNum = getAccidentNum(plateNumberByDriver, workList);

            String violationNum = getViolationNum(plateNumberByDriver, workList);

            String speedNum = getSpeedNum(plateNumberByDriver, workList);

            String fenceNum = getFenceNum(plateNumberByDriver, workList);

            String safetyNum = getSafetyNum(plateNumberByDriver, workList);
            String driverMile = getDriverMileNum(plateNumberByDriver, workList);

            vo.setAccidentNum(accidentNum);
            vo.setViolationNum(violationNum);
            vo.setSpeedNum(speedNum);
            vo.setFenceNum(fenceNum);
            vo.setSafetyNum(safetyNum);
            vo.setDriverMile(driverMile);
            return vo;
        }).collect(Collectors.toList());
        return analysisVOS;
    }


    private String getAccidentNum(List<String> plateNumbers, List<DriverWorkVO> workList) {
        if (plateNumbers.isEmpty()) {
            return "";
        }
        LambdaQueryWrapper<TbAccidentInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(TbAccidentInfo::getPlateNumber, plateNumbers);
        queryWrapper.and(wrapper -> {
            workList.forEach(work -> {
                wrapper.or(inner -> {
                    inner.between(TbAccidentInfo::getAccidentTime, work.getWorkStartTime(), work.getWorkEndTIme());
                });
            });
        });
        int count = iTbAccidentInfoService.count(queryWrapper);
        return String.valueOf(count);
    }

    private String getViolationNum(List<String> plateNumbers, List<DriverWorkVO> workList) {
        if (plateNumbers.isEmpty()) {
            return "";
        }
        LambdaQueryWrapper<TbViolationRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(TbViolationRecord::getPlateNumber, plateNumbers);
        queryWrapper.and(wrapper -> {
            workList.forEach(work -> {
                wrapper.or(inner -> {
                    inner.between(TbViolationRecord::getViolationTime, work.getWorkStartTime(), work.getWorkEndTIme());
                });
            });
        });
        int count = iTbViolationRecordService.count(queryWrapper);
        return String.valueOf(count);
    }

    private String getSpeedNum(List<String> plateNumbers, List<DriverWorkVO> workList) {
        if (plateNumbers.isEmpty()) {
            return "";
        }
        LambdaQueryWrapper<TbGisSpeedingAlarm> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(TbGisSpeedingAlarm::getPlateNumber, plateNumbers);
        queryWrapper.and(wrapper -> {
            workList.forEach(work -> {
                wrapper.or(inner -> {
                    inner.between(TbGisSpeedingAlarm::getStartTime, work.getWorkStartTime(), work.getWorkEndTIme());
                });
            });
        });
        int count = iTbGisSpeedingAlarmService.count(queryWrapper);
        return String.valueOf(count);
    }

    private String getFenceNum(List<String> plateNumbers, List<DriverWorkVO> workList) {
        if (plateNumbers.isEmpty()) {
            return "";
        }
        LambdaQueryWrapper<TbGisFenceAlarm> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(TbGisFenceAlarm::getPlateNumber, plateNumbers);
        queryWrapper.and(wrapper -> {
            workList.forEach(work -> {
                wrapper.or(inner -> {
                    inner.between(TbGisFenceAlarm::getStartTime, work.getWorkStartTime(), work.getWorkEndTIme());
                });
            });
        });
        int count = iTbGisFenceAlarmService.count(queryWrapper);
        return String.valueOf(count);
    }

    private String getSafetyNum(List<String> plateNumbers, List<DriverWorkVO> workList) {
        if (plateNumbers.isEmpty()) {
            return "";
        }
        LambdaQueryWrapper<TbGisActiveSafetyAlarm> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(TbGisActiveSafetyAlarm::getPlateNumber, plateNumbers);
        queryWrapper.and(wrapper -> {
            workList.forEach(work -> {
                wrapper.or(inner -> {
                    inner.between(TbGisActiveSafetyAlarm::getAlertStartTime, work.getWorkStartTime(), work.getWorkEndTIme());
                });
            });
        });
        int count = iTbGisActiveSafetyAlarmService.count(queryWrapper);
        return String.valueOf(count);
    }

    private String getDriverMileNum(List<String> plateNumbers, List<DriverWorkVO> workList) {
        if (plateNumbers.isEmpty()) {
            return "";
        }
        LambdaQueryWrapper<TbGisGps> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(TbGisGps::getPlateNumber, plateNumbers);
        queryWrapper.eq(TbGisGps::getRecordSource, 2);
        queryWrapper.eq(TbGisGps::getIsValid, 1);
        queryWrapper.and(wrapper -> {
            workList.forEach(work -> {
                wrapper.or(inner -> {
                    inner.between(TbGisGps::getGpsTime, work.getWorkStartTime(), work.getWorkEndTIme());
                });
            });
        });
        queryWrapper.orderByAsc(TbGisGps::getGpsTime);
        List<TbGisGps> list = iTbGisGpsService.list(queryWrapper);
        //删除掉脏数据
        list.removeIf(l -> ObjectUtil.isEmpty(l.getTotalMileage()));
        if (list.isEmpty()) {
            return "";
        }
        Map<String, List<TbGisGps>> groupedByPlateNumber = list.stream()
                .collect(Collectors.groupingBy(TbGisGps::getPlateNumber));
        double totalDifference = groupedByPlateNumber.values().stream()
                .mapToDouble(group -> group.get(group.size() - 1).getTotalMileage().subtract(group.get(0).getTotalMileage()).doubleValue())
                .sum();
        return new BigDecimal(totalDifference).setScale(2,BigDecimal.ROUND_HALF_UP).toString();
    }

    private Map<String, VehicleStatisVo> getStringVehicleStatisVoMap(StatisParamVO vo, List<TbVehicle> list, List<RepairStatisVO> repairList, List<UpkeepStatisVO> upkeepList, List<InsuranceStatisVo> insuranceList, List<AnnualInspectionInfoStatisVo> annualInspectionInfoList, List<ViolationRecordStatisVO> violationList) {
        Map<String, List<TbVehicle>> collect = list.stream().collect(Collectors.groupingBy(TbVehicle::getPlateNumber));
        Set<String> strings = collect.keySet();

        //创建一个Map，用于存储项目Id，项目名称和车辆类型为键，ReportListVo为值
        Map<String, VehicleStatisVo> map = new HashMap<>();
        for (RepairStatisVO to : repairList) {
            if (!strings.contains(to.getPlateNumber())) {
                continue;
            }
            TbVehicle vehicle = collect.get(to.getPlateNumber()).get(0);
            //生成一个键，由项目Id，项目名称和车辆类型组成，用逗号分隔
            String key = to.getPlateNumber() + "," + vehicle.getVehicleType() + "," + to.getStatisTime();
            //如果Map中已经存在该键，说明已经有一个ReportListVo对象，那么只需要更新其维修统计字段
            if (map.containsKey(key)) {
                VehicleStatisVo rl = map.get(key);
                rl.setRepairAmount(rl.getRepairAmount() + to.getRepairAmount());
                rl.setVehicleType(vehicle.getVehicleType());
                rl.setVehicleBrand(vehicle.getVehicleBrand());
                rl.setVehicleModel(vehicle.getVehicleModel());
                rl.setFrameNumber(vehicle.getFrameNumber());
                if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) {
                    rl.setPrice(vehicle.getPrice());
                }

            } else {
                //否则，创建一个新的ReportListVo对象，并设置其项目Id，项目名称，车辆类型和维修统计字段
                VehicleStatisVo rl = new VehicleStatisVo();
                rl.setProjectId(to.getProjectId());
                rl.setPlateNumber(to.getPlateNumber());
                rl.setVehicleType(to.getVehicleType());
                rl.setStatisTime(to.getStatisTime());
                rl.setRepairAmount(to.getRepairAmount());
                rl.setVehicleType(vehicle.getVehicleType());
                rl.setVehicleBrand(vehicle.getVehicleBrand());
                rl.setVehicleModel(vehicle.getVehicleModel());
                rl.setFrameNumber(vehicle.getFrameNumber());
                if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) {
                    rl.setPrice(vehicle.getPrice());
                }

                //将新的ReportListVo对象放入Map中
                map.put(key, rl);
            }
        }
        for (UpkeepStatisVO to : upkeepList) {
            if (!strings.contains(to.getPlateNumber())) {
                continue;
            }
            TbVehicle vehicle = collect.get(to.getPlateNumber()).get(0);
            //生成一个键，由项目Id，项目名称和车辆类型组成，用逗号分隔
            String key = to.getPlateNumber() + "," + vehicle.getVehicleType() + "," + to.getStatisTime();
            //如果Map中已经存在该键，说明已经有一个ReportListVo对象，那么只需要更新其维修统计字段
            if (map.containsKey(key)) {
                VehicleStatisVo rl = map.get(key);
                rl.setUpkeepAmount(rl.getUpkeepAmount() + to.getUpkeepAmount());
                rl.setVehicleType(vehicle.getVehicleType());
                rl.setVehicleBrand(vehicle.getVehicleBrand());
                rl.setVehicleModel(vehicle.getVehicleModel());
                rl.setFrameNumber(vehicle.getFrameNumber());
                if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) {
                    rl.setPrice(vehicle.getPrice());
                }

            } else {
                //否则，创建一个新的ReportListVo对象，并设置其项目Id，项目名称，车辆类型和维修统计字段
                VehicleStatisVo rl = new VehicleStatisVo();
                rl.setProjectId(to.getProjectId());
                rl.setPlateNumber(to.getPlateNumber());
                rl.setVehicleType(to.getVehicleType());
                rl.setStatisTime(to.getStatisTime());
                rl.setUpkeepAmount(to.getUpkeepAmount());
                rl.setVehicleType(vehicle.getVehicleType());
                rl.setVehicleBrand(vehicle.getVehicleBrand());
                rl.setVehicleModel(vehicle.getVehicleModel());
                rl.setFrameNumber(vehicle.getFrameNumber());
                if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) {
                    rl.setPrice(vehicle.getPrice());
                }

                //将新的ReportListVo对象放入Map中
                map.put(key, rl);
            }
        }
        for (InsuranceStatisVo to : insuranceList) {
            if (!strings.contains(to.getPlateNumber())) {
                continue;
            }
            TbVehicle vehicle = collect.get(to.getPlateNumber()).get(0);
            //生成一个键，由项目Id，项目名称和车辆类型组成，用逗号分隔
            String key = to.getPlateNumber() + "," + vehicle.getVehicleType() + "," + to.getStatisTime();
            //如果Map中已经存在该键，说明已经有一个ReportListVo对象，那么只需要更新其维修统计字段
            if (map.containsKey(key)) {
                VehicleStatisVo rl = map.get(key);
                rl.setInsuranceAmount(rl.getInsuranceAmount() + to.getTotalPrice());
                rl.setVehicleType(vehicle.getVehicleType());
                rl.setVehicleBrand(vehicle.getVehicleBrand());
                rl.setVehicleModel(vehicle.getVehicleModel());
                rl.setFrameNumber(vehicle.getFrameNumber());
                if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) {
                    rl.setPrice(vehicle.getPrice());
                }

            } else {
                //否则，创建一个新的ReportListVo对象，并设置其项目Id，项目名称，车辆类型和维修统计字段
                VehicleStatisVo rl = new VehicleStatisVo();
                rl.setProjectId(to.getProjectId());
                rl.setPlateNumber(to.getPlateNumber());
                rl.setVehicleType(to.getVehicleType());
                rl.setStatisTime(to.getStatisTime());
                rl.setInsuranceAmount(to.getTotalPrice());
                rl.setVehicleType(vehicle.getVehicleType());
                rl.setVehicleBrand(vehicle.getVehicleBrand());
                rl.setVehicleModel(vehicle.getVehicleModel());
                rl.setFrameNumber(vehicle.getFrameNumber());
                if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) {
                    rl.setPrice(vehicle.getPrice());
                }

                //将新的ReportListVo对象放入Map中
                map.put(key, rl);
            }
        }
        for (AnnualInspectionInfoStatisVo to : annualInspectionInfoList) {
            if (!strings.contains(to.getPlateNumber())) {
                continue;
            }
            TbVehicle vehicle = collect.get(to.getPlateNumber()).get(0);
            //生成一个键，由项目Id，项目名称和车辆类型组成，用逗号分隔
            String key = to.getPlateNumber() + "," + vehicle.getVehicleType() + "," + to.getStatisTime();
            //如果Map中已经存在该键，说明已经有一个ReportListVo对象，那么只需要更新其维修统计字段
            if (map.containsKey(key)) {
                VehicleStatisVo rl = map.get(key);
                rl.setInspectionAmount(rl.getInspectionAmount() + to.getInspectionAmount());
                rl.setVehicleType(vehicle.getVehicleType());
                rl.setVehicleBrand(vehicle.getVehicleBrand());
                rl.setVehicleModel(vehicle.getVehicleModel());
                rl.setFrameNumber(vehicle.getFrameNumber());
                if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) {
                    rl.setPrice(vehicle.getPrice());
                }

            } else {
                //否则，创建一个新的ReportListVo对象，并设置其项目Id，项目名称，车辆类型和维修统计字段
                VehicleStatisVo rl = new VehicleStatisVo();
                rl.setProjectId(to.getProjectId());
                rl.setPlateNumber(to.getPlateNumber());
                rl.setVehicleType(to.getVehicleType());
                rl.setStatisTime(to.getStatisTime());
                rl.setInspectionAmount(to.getInspectionAmount());
                rl.setVehicleType(vehicle.getVehicleType());
                rl.setVehicleBrand(vehicle.getVehicleBrand());
                rl.setVehicleModel(vehicle.getVehicleModel());
                rl.setFrameNumber(vehicle.getFrameNumber());
                if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) {
                    rl.setPrice(vehicle.getPrice());
                }

                //将新的ReportListVo对象放入Map中
                map.put(key, rl);
            }
        }
        for (ViolationRecordStatisVO to : violationList) {
            if (!strings.contains(to.getPlateNumber())) {
                continue;
            }
            TbVehicle vehicle = collect.get(to.getPlateNumber()).get(0);
            //生成一个键，由项目Id，项目名称和车辆类型组成，用逗号分隔
            String key = to.getPlateNumber() + "," + vehicle.getVehicleType() + "," + to.getStatisTime();
            //如果Map中已经存在该键，说明已经有一个ReportListVo对象，那么只需要更新其维修统计字段
            if (map.containsKey(key)) {
                VehicleStatisVo rl = map.get(key);
                rl.setViolationAmount(rl.getViolationAmount() + to.getViolationAmount());
                rl.setVehicleType(vehicle.getVehicleType());
                rl.setVehicleBrand(vehicle.getVehicleBrand());
                rl.setVehicleModel(vehicle.getVehicleModel());
                rl.setFrameNumber(vehicle.getFrameNumber());
                if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) {
                    rl.setPrice(vehicle.getPrice());
                }

            } else {
                //否则，创建一个新的ReportListVo对象，并设置其项目Id，项目名称，车辆类型和维修统计字段
                VehicleStatisVo rl = new VehicleStatisVo();
                rl.setProjectId(to.getProjectId());
                rl.setPlateNumber(to.getPlateNumber());
                rl.setVehicleType(to.getVehicleType());
                rl.setStatisTime(to.getStatisTime());
                rl.setViolationAmount(to.getViolationAmount());
                rl.setVehicleType(vehicle.getVehicleType());
                rl.setVehicleBrand(vehicle.getVehicleBrand());
                rl.setVehicleModel(vehicle.getVehicleModel());
                rl.setFrameNumber(vehicle.getFrameNumber());
                if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) {
                    rl.setPrice(vehicle.getPrice());
                }

                //将新的ReportListVo对象放入Map中
                map.put(key, rl);
            }
        }
        for (TbVehicle to : list) {
            int year = DateUtil.year(to.getDeliveryTime());
            if (StrUtil.isNotBlank(vo.getStartTime())) {
                if (DateUtil.parse(vo.getStartTime()).year() != year) {
                    continue;
                }
            }
            //生成一个键，由项目Id，项目名称和车辆类型组成，用逗号分隔
            String key = to.getPlateNumber() + "," + to.getVehicleType() + "," + year;
            //如果Map中已经存在该键，说明已经有一个ReportListVo对象，那么只需要更新其维修统计字段
            if (map.containsKey(key)) {
                VehicleStatisVo rl = map.get(key);
                rl.setVehicleBrand(to.getVehicleBrand());
                rl.setVehicleModel(to.getVehicleModel());
                rl.setFrameNumber(to.getFrameNumber());
                rl.setVehicleType(to.getVehicleType());
            } else {
                //否则，创建一个新的ReportListVo对象，并设置其项目Id，项目名称，车辆类型和维修统计字段
                VehicleStatisVo rl = new VehicleStatisVo();
                rl.setProjectId(to.getProjectId());
                rl.setPlateNumber(to.getPlateNumber());
                rl.setVehicleType(to.getVehicleType());
                rl.setStatisTime(String.valueOf(year));
                rl.setVehicleBrand(to.getVehicleBrand());
                rl.setVehicleModel(to.getVehicleModel());
                rl.setFrameNumber(to.getFrameNumber());
                rl.setPrice(to.getPrice());
                //将新的ReportListVo对象放入Map中
                map.put(key, rl);
            }
        }
        return map;
    }
}
