package com.ningdatech.carapi.car.equipment.manage;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Repository;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.ningdatech.basic.function.VUtils;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.basic.util.StrPool;
import com.ningdatech.carapi.archives.enums.AuditStateEnum;
import com.ningdatech.carapi.car.equipment.converter.VehicleEquipmentConverter;
import com.ningdatech.carapi.car.equipment.model.DataAccessDevices;
import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentChannels;
import com.ningdatech.carapi.car.equipment.model.NdVehicleEquipmentInfo;
import com.ningdatech.carapi.car.equipment.model.VehicleEquipmentNo;
import com.ningdatech.carapi.car.equipment.model.dto.VehicleEquipmentDTO;
import com.ningdatech.carapi.car.equipment.model.dto.VehicleEquipmentPageQuery;
import com.ningdatech.carapi.car.equipment.model.dto.VehicleEquipmentQueryDTO;
import com.ningdatech.carapi.car.equipment.model.res.SipEquipmentRes;
import com.ningdatech.carapi.car.equipment.model.vo.VehicleEquipmentVO;
import com.ningdatech.carapi.car.equipment.service.IDataAccessDevicesService;
import com.ningdatech.carapi.car.equipment.service.INdVehicleEquipmentChannelsService;
import com.ningdatech.carapi.car.equipment.service.INdVehicleEquipmentInfoService;
import com.ningdatech.carapi.car.equipment.service.IVehicleEquipmentNoService;
import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo;
import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfoJoin;
import com.ningdatech.carapi.car.vehicle.model.dto.VehicleArchivesPageQuery;
import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoJoinService;
import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService;
import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper;
import com.ningdatech.carapi.common.constant.CommonConstant;
import com.ningdatech.carapi.common.constant.UserRoleTypeEnum;
import com.ningdatech.carapi.common.constant.VehicleEquipFuncEnum;
import com.ningdatech.carapi.common.contants.DefValConstants;
import com.ningdatech.carapi.common.util.ExcelDownUtil;
import com.ningdatech.carapi.datascope.aop.LambdaDataScope;
import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum;
import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO;
import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper;
import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails;
import com.ningdatech.carapi.user.util.LoginUserUtil;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @Classname VehicleEquipmentRepository
 * @Description
 * @Date 2022/10/14 14:33
 * @Created by PoffyZhang
 */
@Repository
@RequiredArgsConstructor
@Slf4j
public class VehicleEquipmentManage {

    private final IVehicleBaseInfoJoinService vehicleBaseInfoJoinService;

    private final IVehicleBaseInfoService vehicleBaseInfoService;
    private final INdVehicleEquipmentInfoService vehicleEquipmentInfoService;
    private final INdVehicleEquipmentChannelsService vehicleEquipmentChannelsService;
    private final OperatorsCacheHelper operatorsCacheHelper;
    private final IDataAccessDevicesService dataAccessDevicesService;
    private final IVehicleEquipmentNoService vehicleEquipmentNoService;

    public PageVo<VehicleEquipmentVO> queryToBeAdded(VehicleArchivesPageQuery vehicleArchivesPageQuery) {

        // 按照登录用户，如果是运营商账号登录，删选出该运营商关联的车辆信息
        UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
        Long roleId = userDetail.getRoleId();
        if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) {
            String companyName = userDetail.getCompanyName();
            // 暂时控制运营商名称和运营商所在企业名称相同
            OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName);
            // 获取运营商id、名字
            Long operatorId = operatorQueryDTO.getId();

            Page<NdVehicleBaseInfoJoin> page = vehicleArchivesPageQuery.page();
            LambdaQueryWrapper<NdVehicleBaseInfoJoin> wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class);
            buildBaseInfoQueryWrapper(wrapper,vehicleArchivesPageQuery);
            wrapper.eq(NdVehicleBaseInfoJoin::getOperatorId,operatorId);
            vehicleBaseInfoJoinService.pageJoinWithNotEquipment(page,wrapper);
            List<VehicleEquipmentVO> data = CollUtils.convert(page.getRecords(), VehicleEquipmentConverter::convert);
            return PageVo.of(data, page.getTotal());
        } else if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId)) {
            Long companyId = userDetail.getCompanyId();
            Page<NdVehicleBaseInfoJoin> page = vehicleArchivesPageQuery.page();
            LambdaQueryWrapper<NdVehicleBaseInfoJoin> wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class);
            buildBaseInfoQueryWrapper(wrapper,vehicleArchivesPageQuery);
            wrapper.and(w -> w.eq(NdVehicleBaseInfoJoin::getCompanyId,companyId).or()
                    .eq(NdVehicleBaseInfoJoin::getUseCompanyId,companyId));
            vehicleBaseInfoJoinService.pageJoinWithNotEquipmentAndUseCompany(page,wrapper);
            List<VehicleEquipmentVO> data = CollUtils.convert(page.getRecords(), VehicleEquipmentConverter::convert);
            return PageVo.of(data, page.getTotal());
        } else {
            Page<NdVehicleBaseInfoJoin> page = vehicleArchivesPageQuery.page();
            LambdaQueryWrapper<NdVehicleBaseInfoJoin> wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class);
            VehicleEquipmentManage context = (VehicleEquipmentManage) AopContext.currentProxy();
            context.searchTobeAddedPage(page, wrapper, vehicleArchivesPageQuery);
            List<VehicleEquipmentVO> data = CollUtils.convert(page.getRecords(), VehicleEquipmentConverter::convert);
            return PageVo.of(data, page.getTotal());
        }
    }

    @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1)
    public void searchTobeAddedPage(Page<NdVehicleBaseInfoJoin> page, LambdaQueryWrapper<NdVehicleBaseInfoJoin> wrapper,
                                    VehicleArchivesPageQuery vehicleArchivesPageQuery) {
        buildBaseInfoQueryWrapper(wrapper,vehicleArchivesPageQuery);
        vehicleBaseInfoJoinService.pageJoinWithNotEquipment(page,wrapper);
    }

    public PageVo<VehicleEquipmentVO> queryAdded(VehicleEquipmentPageQuery vehicleArchivesPageQuery) {
        // 按照登录用户，如果是运营商账号登录，删选出该运营商关联的车辆信息
        UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
        Long roleId = userDetail.getRoleId();
        if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) {
            String companyName = userDetail.getCompanyName();
            // 暂时控制运营商名称和运营商所在企业名称相同
            OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName);
            // 获取运营商id
            VUtils.isTrue(Objects.isNull(operatorQueryDTO)).throwMessage("运营商：" + companyName + "不存在！");
            Long operatorId = operatorQueryDTO.getId();

            Page<NdVehicleBaseInfoJoin> page = vehicleArchivesPageQuery.page();
            LambdaQueryWrapper<NdVehicleBaseInfoJoin> wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class);
            buildQueryWrapper(wrapper,vehicleArchivesPageQuery);
            wrapper.eq(NdVehicleBaseInfoJoin::getOperatorId,operatorId);
            vehicleBaseInfoJoinService.pageJoinWithEquipment(page,wrapper);
            List<VehicleEquipmentVO> data = CollUtils.convert(page.getRecords(), VehicleEquipmentConverter::convert);
            return PageVo.of(data, page.getTotal());
        } else if (UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId().equals(roleId)) {
            Long companyId = userDetail.getCompanyId();
            Page<NdVehicleBaseInfoJoin> page = vehicleArchivesPageQuery.page();
            LambdaQueryWrapper<NdVehicleBaseInfoJoin> wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class);
            buildQueryWrapper(wrapper,vehicleArchivesPageQuery);
            wrapper.and(w -> w.eq(NdVehicleBaseInfoJoin::getCompanyId,companyId).or()
                    .eq(NdVehicleBaseInfoJoin::getUseCompanyId,companyId));
            vehicleBaseInfoJoinService.pageJoinWithEquipmentAndUseCompany(page,wrapper);
            List<VehicleEquipmentVO> data = CollUtils.convert(page.getRecords(), VehicleEquipmentConverter::convert);
            return PageVo.of(data, page.getTotal());
        } else {
            Page<NdVehicleBaseInfoJoin> page = vehicleArchivesPageQuery.page();
            LambdaQueryWrapper<NdVehicleBaseInfoJoin> wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfoJoin.class);
            VehicleEquipmentManage context = (VehicleEquipmentManage) AopContext.currentProxy();
            context.searchAddedPage(page, wrapper, vehicleArchivesPageQuery);
            List<VehicleEquipmentVO> data = CollUtils.convert(page.getRecords(), VehicleEquipmentConverter::convert);
            return PageVo.of(data, page.getTotal());
        }
    }

    @BuildChildrenRegionWrapper(entityIndex = 2,wrapperIndex = 1)
    public void searchAddedPage(Page<NdVehicleBaseInfoJoin> page,
                                LambdaQueryWrapper<NdVehicleBaseInfoJoin> wrapper, VehicleEquipmentPageQuery vehicleArchivesPageQuery) {
        buildQueryWrapper(wrapper,vehicleArchivesPageQuery);
        vehicleBaseInfoJoinService.pageJoinWithEquipment(page,wrapper);
    }

    public VehicleEquipmentQueryDTO getEquipmentById(Long id) {

        NdVehicleEquipmentInfo vehicleEquipmentInfo = vehicleEquipmentInfoService.getById(id);
        if (Objects.isNull(vehicleEquipmentInfo)){
            return null;
        }
        Long vehicleId = vehicleEquipmentInfo.getVehicleId();

        LambdaQueryWrapper<NdVehicleBaseInfo> wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class);
        VehicleEquipmentManage context = (VehicleEquipmentManage) AopContext.currentProxy();
        context.buildQuery(wrapper, vehicleId);
        NdVehicleBaseInfo ndVehicleBaseInfo = vehicleBaseInfoService.getOne(wrapper);
        // 设备所属的车辆，当前登录用户没有权限查看
        if (Objects.isNull(ndVehicleBaseInfo)){
            return null;
        }

        VehicleEquipmentQueryDTO query = BeanUtil.toBean(vehicleEquipmentInfo, VehicleEquipmentQueryDTO.class);
        if(Objects.nonNull(query)){
            query.setChannels(vehicleEquipmentChannelsService.list(Wrappers.lambdaQuery(NdVehicleEquipmentChannels.class)
                    .eq(NdVehicleEquipmentChannels::getEquipmentId,query.getId())));
            if(Objects.nonNull(vehicleEquipmentInfo.getSubordinatePlatform()) &&
                    StringUtils.isNumeric(vehicleEquipmentInfo.getSubordinatePlatform())){
                query.setSubordinatePlatform(Long.valueOf(vehicleEquipmentInfo.getSubordinatePlatform()));
            }

        }
        return query;
    }

    @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL)
    public void buildQuery(LambdaQueryWrapper<NdVehicleBaseInfo> wrapper, Long id) {
        wrapper.eq(NdVehicleBaseInfo::getId,id);
    }


    public List<VehicleEquipmentQueryDTO> getEquipmentByCarPlate(String carPlate) {
        LambdaQueryWrapper<NdVehicleEquipmentInfo> wrapper = Wrappers.lambdaQuery(NdVehicleEquipmentInfo.class);
        wrapper.eq(NdVehicleEquipmentInfo::getCarPlate,carPlate);
        wrapper.eq(NdVehicleEquipmentInfo::getEquipmentFunction, VehicleEquipFuncEnum.video.name());
        List<NdVehicleEquipmentInfo> vehicleEquipments = vehicleEquipmentInfoService.list(wrapper);
        return CollUtils.convert(vehicleEquipments, w -> {
            VehicleEquipmentQueryDTO equipmentQueryDTO = BeanUtil.copyProperties(w, VehicleEquipmentQueryDTO.class);
            if(Objects.nonNull(w.getSubordinatePlatform()) &&
                    StringUtils.isNumeric(w.getSubordinatePlatform())){
                equipmentQueryDTO.setSubordinatePlatform(Long.valueOf(w.getSubordinatePlatform()));
            }
            return equipmentQueryDTO;
        });
    }

    public List<VehicleEquipmentQueryDTO> getEquipment(Long vehicleId) {
        List<NdVehicleEquipmentInfo> vehicleEquipments = vehicleEquipmentInfoService
                .list(Wrappers.lambdaQuery(NdVehicleEquipmentInfo.class).eq(NdVehicleEquipmentInfo::getVehicleId,vehicleId));
        List<VehicleEquipmentQueryDTO> res = CollUtils.convert(vehicleEquipments, e -> BeanUtil.copyProperties(e,VehicleEquipmentQueryDTO.class));
        if(CollUtil.isNotEmpty(res)){
            for(VehicleEquipmentQueryDTO dto: res){
                dto.setChannels(vehicleEquipmentChannelsService.list(Wrappers.lambdaQuery(NdVehicleEquipmentChannels.class)
                        .eq(NdVehicleEquipmentChannels::getEquipmentId,dto.getId())));
                dto.setSubordinatePlatformName(operatorsCacheHelper.getNameById(dto.getSubordinatePlatform()));
            }
        }
        return res;
    }

    /**
     * 处理regionCode 拼接
     * @param wrapper
     * @param vehicleEquipmentPageQuery
     */
    private void buildQueryWrapper(LambdaQueryWrapper<NdVehicleBaseInfoJoin> wrapper, VehicleEquipmentPageQuery vehicleEquipmentPageQuery) {
        wrapper.like(StringUtils.isNotBlank(vehicleEquipmentPageQuery.getCarPlate()), NdVehicleBaseInfoJoin::getCarPlate, vehicleEquipmentPageQuery.getCarPlate())
                .like(StringUtils.isNotBlank(vehicleEquipmentPageQuery.getCompanyName()), NdVehicleBaseInfoJoin::getCompanyName, vehicleEquipmentPageQuery.getCompanyName())
                .eq(Objects.nonNull(vehicleEquipmentPageQuery.getVehicleType()), NdVehicleBaseInfoJoin::getVehicleType, vehicleEquipmentPageQuery.getVehicleType())
                .eq(Objects.nonNull(vehicleEquipmentPageQuery.getVehicleStatus()),NdVehicleBaseInfoJoin::getVehicleStatus,vehicleEquipmentPageQuery.getVehicleStatus())
                //只有审核成功的才会进入该列表
                .eq(NdVehicleBaseInfoJoin::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode())
                .like(StringUtils.isNotBlank(vehicleEquipmentPageQuery.getOperatorName()), NdVehicleBaseInfoJoin::getOperatorName, vehicleEquipmentPageQuery.getOperatorName())
                .orderBy(Boolean.TRUE,Boolean.FALSE,NdVehicleBaseInfoJoin::getUpdateOn);
    }


    /**
     *
     * @param wrapper
     * @param vehicleArchivesPageQuery
     */
    private void buildBaseInfoQueryWrapper(LambdaQueryWrapper<NdVehicleBaseInfoJoin> wrapper,
                                           VehicleArchivesPageQuery vehicleArchivesPageQuery) {
        wrapper.like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getCarPlate()), NdVehicleBaseInfoJoin::getCarPlate, vehicleArchivesPageQuery.getCarPlate())
                .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getCompanyName()), NdVehicleBaseInfoJoin::getCompanyName, vehicleArchivesPageQuery.getCompanyName())
                .eq(Objects.nonNull(vehicleArchivesPageQuery.getVehicleType()), NdVehicleBaseInfoJoin::getVehicleType, vehicleArchivesPageQuery.getVehicleType())
                .eq(Objects.nonNull(vehicleArchivesPageQuery.getVehicleStatus()),NdVehicleBaseInfoJoin::getVehicleStatus,vehicleArchivesPageQuery.getVehicleStatus())
                //只有审核成功的才会进入该列表
                .eq(NdVehicleBaseInfoJoin::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode())
                .like(StringUtils.isNotBlank(vehicleArchivesPageQuery.getOperatorName()), NdVehicleBaseInfoJoin::getOperatorName, vehicleArchivesPageQuery.getOperatorName())
                .orderBy(Boolean.TRUE,Boolean.FALSE,NdVehicleBaseInfoJoin::getUpdateOn);

    }

    public void export(HttpServletResponse response, VehicleEquipmentPageQuery equipmentPageQuery) {
        equipmentPageQuery.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE);
        VehicleArchivesPageQuery vehicleArchivesPageQuery = BeanUtil.copyProperties(equipmentPageQuery,VehicleArchivesPageQuery.class);
        PageVo<VehicleEquipmentVO> toBePage = queryToBeAdded(vehicleArchivesPageQuery);
        PageVo<VehicleEquipmentVO> addPage = queryAdded(equipmentPageQuery);
        List<VehicleEquipmentVO> toBeList = toBePage.getRecords().stream().map(w -> BeanUtil.copyProperties(w, VehicleEquipmentVO.class)).collect(Collectors.toList());
        List<VehicleEquipmentVO> auditList = addPage.getRecords().stream().map(w -> BeanUtil.copyProperties(w, VehicleEquipmentVO.class)).collect(Collectors.toList());
        String fileName = "车辆设备列表";
        ExcelDownUtil.setFileName(fileName, response);
        // 数据导出处理函数
        String sheetNameToBe = "车辆设备待安装列表";
        String sheetNameAdded = "车辆设备已安装列表";
        try {
            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
            //埋点基础信息 sheet
            WriteSheet writeSheet = EasyExcel.writerSheet(0, sheetNameToBe)
                    .head(VehicleEquipmentDTO.class).build();
            excelWriter.write(toBeList, writeSheet);
            //埋点数据转换信息 sheet
            writeSheet = EasyExcel.writerSheet(1, sheetNameAdded)
                    .head(VehicleEquipmentDTO.class).build();
            excelWriter.write(auditList, writeSheet);
            excelWriter.finish();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 从sip获取到 该车牌号的设备
     * @param car_plate
     * @return
     */
    public Boolean initEquipmentFromSip(String car_plate) {
        List<SipEquipmentRes> sipEquipments = vehicleEquipmentInfoService.getSipEquipmentsByCarPlate(car_plate);
        if(CollUtil.isNotEmpty(sipEquipments)){
            //如果有设备的话 就去更新这个车牌下的所有设备
            //1.查看系统里 是否有这个车牌号
            NdVehicleBaseInfo vehicle = vehicleBaseInfoService.getOne(
                    Wrappers.lambdaQuery(NdVehicleBaseInfo.class).eq(NdVehicleBaseInfo::getCarPlate,car_plate)
                            .eq(NdVehicleBaseInfo::getDeleted,Boolean.FALSE)
                            .eq(NdVehicleBaseInfo::getAuditState,AuditStateEnum.AUDIT_SUCCESS.getCode()));
            if(Objects.isNull(vehicle)){
                log.warn("该车辆 【{}】不存在 系统中",car_plate);
                return Boolean.FALSE;
            }
            //2.先删除现有的设备
            vehicleEquipmentInfoService.remove(Wrappers.lambdaQuery(NdVehicleEquipmentInfo.class)
                    .eq(NdVehicleEquipmentInfo::getCarPlate,car_plate));
            List<NdVehicleEquipmentInfo> toAdds = sipEquipments.stream()
                    .filter(e -> Objects.nonNull(e) && StringUtils.isNotBlank(e.getDevice_id()))
                    .map(e -> {
                        NdVehicleEquipmentInfo equipmentInfo = new NdVehicleEquipmentInfo();
                        equipmentInfo.setName(e.getName());
                        equipmentInfo.setEquipmentNo(e.getDevice_id());
                        equipmentInfo.setCarPlate(car_plate);
                        equipmentInfo.setVehicleId(vehicle.getId());
                        equipmentInfo.setSubordinatePlatform(e.getPlatform_id());
                        return equipmentInfo;
                    }).collect(Collectors.toList());
            //3.再批量添加
            vehicleEquipmentInfoService.saveBatch(toAdds);
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    public Boolean initEquipmentFromSipAll() {
        //1.查看系统里 审核过的车牌号
        List<NdVehicleBaseInfo> vehicles = vehicleBaseInfoService.list(
                Wrappers.lambdaQuery(NdVehicleBaseInfo.class)
                        .eq(NdVehicleBaseInfo::getDeleted,Boolean.FALSE)
                        .eq(NdVehicleBaseInfo::getAuditState,AuditStateEnum.AUDIT_SUCCESS.getCode()));
        Integer total = 0;
        if(CollUtil.isNotEmpty(vehicles)){
            //2.去遍历 并且添加车辆的设备
            for(NdVehicleBaseInfo vehicle  : vehicles){
                if(StringUtils.isNotBlank(vehicle.getCarPlate())){
                    List<SipEquipmentRes> sipEquipments = vehicleEquipmentInfoService.getSipEquipmentsByCarPlate(vehicle.getCarPlate());
                    //2.先删除现有的设备
                    vehicleEquipmentInfoService.remove(Wrappers.lambdaQuery(NdVehicleEquipmentInfo.class)
                            .eq(NdVehicleEquipmentInfo::getCarPlate,vehicle.getCarPlate()));
                    if(CollUtil.isNotEmpty(sipEquipments)){
                        List<NdVehicleEquipmentInfo> toAdds = sipEquipments.stream()
                                .filter(e -> Objects.nonNull(e) && StringUtils.isNotBlank(e.getDevice_id()))
                                .map(e -> {
                                    NdVehicleEquipmentInfo equipmentInfo = new NdVehicleEquipmentInfo();
                                    equipmentInfo.setName(e.getName());
                                    equipmentInfo.setEquipmentNo(e.getDevice_id());
                                    equipmentInfo.setCarPlate(vehicle.getCarPlate());
                                    equipmentInfo.setVehicleId(vehicle.getId());
                                    equipmentInfo.setSubordinatePlatform("1");
                                    return equipmentInfo;
                                }).collect(Collectors.toList());
                        //3.再批量添加
                        total += toAdds.size();
                        if(CollUtil.isNotEmpty(toAdds)){
                            vehicleEquipmentInfoService.insertBatch(toAdds);
                        }
                        log.info("当前插入了 total :{}",total);
                    }
                }
            }
            log.info("最后的批量插入了 total :{}",total);
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    public void getEquipNo() {
        // 获取系统中所有车牌号
        List<String> carPlateList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class)
                        .eq(NdVehicleBaseInfo::getAuditState, AuditStateEnum.AUDIT_SUCCESS.getCode())
                        .select(NdVehicleBaseInfo::getCarPlate)
                        .isNotNull(NdVehicleBaseInfo::getCarPlate))
                .stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList());
        // 获取实时视频设备表中的车牌号集合
        Set<String> dataCarPlates = dataAccessDevicesService.list(Wrappers.lambdaQuery(DataAccessDevices.class)
                        .select(DataAccessDevices::getCarPlate))
                .stream().filter(Objects::nonNull).map(DataAccessDevices::getCarPlate)
                .collect(Collectors.toSet());
        // 获取在系统中的车牌号
        List<String> carNoList = dataCarPlates.stream().filter(carPlateList::contains).collect(Collectors.toList());
        log.info("存在于系统中的车牌号数量:{}", carNoList.size());
        // 获取实时视频设备表中所有数据 并按车牌号分组
        Map<String, List<DataAccessDevices>> devicesDataMap = dataAccessDevicesService.list(Wrappers.lambdaQuery(DataAccessDevices.class)
                        .isNotNull(DataAccessDevices::getDeviceId)
                        .isNotNull(DataAccessDevices::getPlatformId)
                        .select(DataAccessDevices::getId, DataAccessDevices::getCarPlate, DataAccessDevices::getDeviceId,
                                DataAccessDevices::getStatus,DataAccessDevices::getPlatformId)
                        .in(DataAccessDevices::getCarPlate,carNoList))
                .stream().collect(Collectors.groupingBy(DataAccessDevices::getCarPlate));
        // 实时视频设备表中车牌号集合
        Set<String> deviceCarPlates = devicesDataMap.keySet();

        // 获取同步设备编号表中的数据
        Map<String, List<VehicleEquipmentNo>> dataMap = vehicleEquipmentNoService.list(Wrappers.lambdaQuery(VehicleEquipmentNo.class)
                        .select(VehicleEquipmentNo::getId, VehicleEquipmentNo::getCarPlate,
                                VehicleEquipmentNo::getDeviceId, VehicleEquipmentNo::getStatus, VehicleEquipmentNo::getPlatformId))
                .stream().collect(Collectors.groupingBy(VehicleEquipmentNo::getCarPlate));
        // 同步设备编号表中车牌号集合
        Set<String> carPlates = dataMap.keySet();

        // 判断数据是否需要新增、删除或者更新
        // 新增：实时视频设备表中有的车牌号而同步设备表中没有
        Set<String> addCarPlates = deviceCarPlates.stream().filter(d -> !carPlates.contains(d)).collect(Collectors.toSet());
        if (CollUtil.isNotEmpty(addCarPlates)){
            addCarPlates.forEach(d -> {
                List<DataAccessDevices> dataAccessDevices = devicesDataMap.get(d);
                List<VehicleEquipmentNo> addDataList = Lists.newArrayList();
                int i = 1;
                for (DataAccessDevices dataAccessDevice : dataAccessDevices) {
                    VehicleEquipmentNo vehicleEquipmentNo = new VehicleEquipmentNo();
                    vehicleEquipmentNo.setCarPlate(d);
                    vehicleEquipmentNo.setDeviceId(dataAccessDevice.getDeviceId());
                    vehicleEquipmentNo.setDeviceName(d + StrPool.DASH + DefValConstants.TONG_DAO + i++);
                    String status = dataAccessDevice.getStatus();
                    if (StringUtils.isNotBlank(status)) {
                        vehicleEquipmentNo.setStatus(status);
                    }
                    vehicleEquipmentNo.setPlatformId(dataAccessDevice.getPlatformId());
                    vehicleEquipmentNo.setCreateBy(1L);
                    vehicleEquipmentNo.setCreateOn(LocalDateTime.now());
                    vehicleEquipmentNo.setUpdateBy(1L);
                    vehicleEquipmentNo.setUpdateOn(LocalDateTime.now());
                    addDataList.add(vehicleEquipmentNo);
                }
                vehicleEquipmentNoService.saveBatch(addDataList);
            });
        }
        // 删除：实时视频设备表中没有车牌号而同步设备表中有
        Set<String> delCarPlates = carPlates.stream().filter(d -> !deviceCarPlates.contains(d)).collect(Collectors.toSet());
        if (CollUtil.isNotEmpty(delCarPlates)){
            vehicleEquipmentNoService.remove(Wrappers.lambdaQuery(VehicleEquipmentNo.class)
                    .in(VehicleEquipmentNo::getCarPlate, delCarPlates));
        }

        // 更新：实时视频设备表和同步设备编号表中对应车牌号下对应ID的设备编号、设备状态不一致或者不存在
        for (Map.Entry<String, List<VehicleEquipmentNo>> entry : dataMap.entrySet()) {
            String carPlate = entry.getKey();
            List<VehicleEquipmentNo> equipmentNos = entry.getValue();
            List<DataAccessDevices> dataAccessDevices = devicesDataMap.get(carPlate);

            // 如果当前车牌号对应的设备编号及设备状态完全相同，则不做任何操作
            Set<String> data = equipmentNos.stream().map(e -> e.getDeviceId() + StrPool.DASH + e.getStatus()).collect(Collectors.toSet());
            Set<String> deviceData = dataAccessDevices.stream().map(d -> {
                String status = d.getStatus();
                if (StrPool.EMPTY.equals(status)) {
                    status = StrPool.NULL;
                }
                return d.getDeviceId() + StrPool.DASH + status;
            }).collect(Collectors.toSet());
            if (data.equals(deviceData)) {
                log.info("车牌号:{}下的设备编号及设备状态完全相同，无需更新", carPlate);
                continue;
            }

            Map<String, VehicleEquipmentNo> equipmentNoMap = equipmentNos.stream().collect(Collectors.toMap(e -> e.getDeviceId() + StrPool.DASH + e.getPlatformId(), e -> e));
            Map<String, DataAccessDevices> dataAccessDevicesMap = dataAccessDevices.stream().collect(Collectors.toMap(d -> d.getDeviceId() + StrPool.DASH + d.getPlatformId(), d -> d));

            // 如果对应车牌号下的设备数不为0，先删除再保存
            if (CollUtil.isNotEmpty(equipmentNoMap) && CollUtil.isNotEmpty(dataAccessDevicesMap)) {
                vehicleEquipmentNoService.remove(Wrappers.lambdaQuery(VehicleEquipmentNo.class)
                        .eq(VehicleEquipmentNo::getCarPlate, carPlate));
                int index = 1;
                List<VehicleEquipmentNo> addDataList = Lists.newArrayList();
                for (Map.Entry<String, DataAccessDevices> devicesEntry : dataAccessDevicesMap.entrySet()) {
                    String[] split = devicesEntry.getKey().split(StrPool.DASH);
                    String addEquipNo = split[0];
                    DataAccessDevices accessDevices = devicesEntry.getValue();
                    VehicleEquipmentNo vehicleEquipmentNo = new VehicleEquipmentNo();
                    vehicleEquipmentNo.setCarPlate(carPlate);
                    vehicleEquipmentNo.setDeviceId(addEquipNo);
                    vehicleEquipmentNo.setDeviceName(carPlate + StrPool.DASH + DefValConstants.TONG_DAO + index++);
                    if (Objects.nonNull(accessDevices)){
                        String status = accessDevices.getStatus();
                        if (StringUtils.isNotBlank(status)) {
                            vehicleEquipmentNo.setStatus(status);
                        }
                    }
                    vehicleEquipmentNo.setPlatformId(accessDevices.getPlatformId());
                    vehicleEquipmentNo.setCreateBy(1L);
                    vehicleEquipmentNo.setCreateOn(LocalDateTime.now());
                    vehicleEquipmentNo.setUpdateBy(1L);
                    vehicleEquipmentNo.setUpdateOn(LocalDateTime.now());
                    addDataList.add(vehicleEquipmentNo);
                }
                vehicleEquipmentNoService.saveBatch(addDataList);

            }
        }
    }
}
