package com.ningdatech.carapi.analysis.manage;

import java.io.IOException;
import java.io.InputStream;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

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.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.carapi.analysis.common.DangerLevelEnum;
import com.ningdatech.carapi.analysis.entity.VehicleAccidentEval;
import com.ningdatech.carapi.analysis.entity.VehicleOverSpeedEval;
import com.ningdatech.carapi.analysis.entity.VehicleServiceLife;
import com.ningdatech.carapi.analysis.entity.VehicleViolationEval;
import com.ningdatech.carapi.analysis.entity.dto.OutDangerImportDto;
import com.ningdatech.carapi.analysis.entity.dto.VehicleAccidentImportDto;
import com.ningdatech.carapi.analysis.entity.dto.VehicleOverSpeedImportDto;
import com.ningdatech.carapi.analysis.entity.dto.VehicleViolationImportDto;
import com.ningdatech.carapi.analysis.entity.req.VehicleAccidentEvalModReq;
import com.ningdatech.carapi.analysis.entity.req.VehicleOverSpeedEvalModReq;
import com.ningdatech.carapi.analysis.entity.req.VehicleServiceLifeListReq;
import com.ningdatech.carapi.analysis.entity.req.VehicleViolationEvalModReq;
import com.ningdatech.carapi.analysis.entity.vo.VehicleAccidentEvalListVo;
import com.ningdatech.carapi.analysis.entity.vo.VehicleOverSpeedEvalListVo;
import com.ningdatech.carapi.analysis.entity.vo.VehicleServiceLifeListVo;
import com.ningdatech.carapi.analysis.entity.vo.VehicleViolationEvalListVo;
import com.ningdatech.carapi.analysis.service.IVehicleAccidentEvalService;
import com.ningdatech.carapi.analysis.service.IVehicleOverSpeedEvalService;
import com.ningdatech.carapi.analysis.service.IVehicleServiceLifeService;
import com.ningdatech.carapi.analysis.service.IVehicleViolationEvalService;
import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo;
import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService;
import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper;
import com.ningdatech.carapi.common.util.CodeUtil;
import com.ningdatech.carapi.datascope.aop.LambdaDataScope;
import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum;
import com.ningdatech.carapi.safe.entity.NdInsureInfo;
import com.ningdatech.carapi.safe.entity.NdInsureOutDanger;
import com.ningdatech.carapi.safe.service.INdInsureInfoService;
import com.ningdatech.carapi.safe.service.INdInsureOutDangerService;
import com.ningdatech.carapi.safe.service.IVehicleAccidentReportService;
import com.ningdatech.carapi.scheduler.enums.DataTypeEnum;
import com.ningdatech.carapi.sys.entity.Company;
import com.ningdatech.carapi.sys.entity.constant.ImportTemplateConstant;
import com.ningdatech.carapi.sys.entity.enumeration.ImportTemplateEnum;
import com.ningdatech.carapi.sys.helper.RegionsCacheHelper;
import com.ningdatech.carapi.sys.service.CompanyService;
import com.ningdatech.carapi.user.util.LoginUserUtil;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * InsuranceRiskEvalManage
 * </p>
 *
 * @author WendyYang
 * @since 14:31 2022/10/15
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class InsuranceRiskEvalManage {

    private final IVehicleServiceLifeService vehicleServiceLifeService;
    private final IVehicleViolationEvalService vehicleViolationEvalService;
    private final IVehicleOverSpeedEvalService vehicleOverSpeedEvalService;
    private final IVehicleAccidentEvalService vehicleAccidentEvalService;
    private final INdInsureOutDangerService ndInsureOutDangerService;
    private final RegionsCacheHelper regionsCacheHelper;
    private final IVehicleBaseInfoService vehicleBaseInfoService;
    private final CompanyService companyService;
    private final INdInsureInfoService insureInfoService;

    private final ApplicationContext applicationContext;

    private final IVehicleAccidentReportService vehicleAccidentReportService;

    /**
     * 车辆使用年限列表
     */
    public PageVo<VehicleServiceLifeListVo> vehicleServiceLifeList(VehicleServiceLifeListReq req) {
        LambdaQueryWrapper<VehicleServiceLife> query = Wrappers.lambdaQuery(VehicleServiceLife.class);
        InsuranceRiskEvalManage context = (InsuranceRiskEvalManage) AopContext.currentProxy();
        context.buildVehicleServiceLife(query,req);
        Page<VehicleServiceLife> page = vehicleServiceLifeService.page(req.page(), query);
        List<VehicleServiceLifeListVo> res = page.getRecords().stream().map(w -> {
            VehicleServiceLifeListVo vo = BeanUtil.copyProperties(w,VehicleServiceLifeListVo.class);
            vo.setRegions(regionsCacheHelper.listParents(w.getRegionId()));
            int usedTime = Optional.ofNullable(w.getBuyTime())
                    .flatMap(time -> Optional.ofNullable((int) ChronoUnit.YEARS.between(time, LocalDate.now())))
                    .orElse(0);
            vo.setUsedTime(usedTime);
            // TODO 车辆使用年限百分比
            vo.setUsedTimePercent(0);
            CodeUtil.searchCompanyName(vo);
            return vo;
        }).collect(Collectors.toList());
        return PageVo.of(res, page.getTotal());
    }
    @LambdaDataScope
    @BuildChildrenRegionWrapper
    public void buildVehicleServiceLife(LambdaQueryWrapper<VehicleServiceLife> query,VehicleServiceLifeListReq req) {
        query.ge(req.getBuyTimeStart() != null, VehicleServiceLife::getBuyTime, req.getBuyTimeStart())
             .le(req.getBuyTimeEnd() != null, VehicleServiceLife::getBuyTime, req.getBuyTimeEnd())
             .like(StrUtil.isNotBlank(req.getCompanyName()), VehicleServiceLife::getCompanyName, req.getCompanyName())
             .like(StrUtil.isNotBlank(req.getCarNo()), VehicleServiceLife::getCarNo, req.getCarNo())
             .eq(Objects.nonNull(req.getDangerLevel()), VehicleServiceLife::getDangerLevel, req.getDangerLevel());
    }

    /**
     * 车辆违章情况列表
     *
     */
    public PageVo<VehicleViolationEvalListVo> vehicleViolationEvalList(VehicleServiceLifeListReq req) {
        LambdaQueryWrapper<VehicleViolationEval> query = Wrappers.lambdaQuery(VehicleViolationEval.class);
        InsuranceRiskEvalManage context = (InsuranceRiskEvalManage) AopContext.currentProxy();
        context.buildVehicleViolationEvalQuery(query,req);
        buildVehicleViolationEvalQuery(query,req);
        Page<VehicleViolationEval> page = vehicleViolationEvalService.page(req.page(), query);
        List<VehicleViolationEvalListVo> res = page.getRecords().stream().map(w -> {
            VehicleViolationEvalListVo vo = BeanUtil.copyProperties(w,VehicleViolationEvalListVo.class);
            vo.setRegions(regionsCacheHelper.listParents(w.getRegionId()));
            vo.setDangerLevelName(DangerLevelEnum.getDescByCode(w.getDangerLevel()));
            CodeUtil.searchCompanyName(vo);
            return vo;
        }).collect(Collectors.toList());
        return PageVo.of(res, page.getTotal());
    }
    @LambdaDataScope
    @BuildChildrenRegionWrapper
    public void buildVehicleViolationEvalQuery(LambdaQueryWrapper<VehicleViolationEval> query,VehicleServiceLifeListReq req) {
        query.like(StrUtil.isNotBlank(req.getCompanyName()),VehicleViolationEval::getCompanyName, req.getCompanyName())
             .like(StrUtil.isNotBlank(req.getCarNo()),VehicleViolationEval::getCarNo, req.getCarNo())
             .eq(Objects.nonNull(req.getDangerLevel()),VehicleViolationEval::getDangerLevel, req.getDangerLevel());
    }

    /**
     * 车辆出险情况列表
     */
    public PageVo<VehicleAccidentEvalListVo> vehicleAccidentList(VehicleServiceLifeListReq req) {
        LambdaQueryWrapper<VehicleAccidentEval> query = Wrappers.lambdaQuery(VehicleAccidentEval.class);
        InsuranceRiskEvalManage context = (InsuranceRiskEvalManage) AopContext.currentProxy();
        context.buildVehicleAccident(query,req);
        Page<VehicleAccidentEval> page = vehicleAccidentEvalService.page(req.page(), query);
        List<VehicleAccidentEvalListVo> res = page.getRecords().stream().map(w -> {
            VehicleAccidentEvalListVo vo = BeanUtil.copyProperties(w,VehicleAccidentEvalListVo.class);
            vo.setRegions(regionsCacheHelper.listParents(w.getRegionId()));
            vo.setDangerLevelName(DangerLevelEnum.getDescByCode(w.getDangerLevel()));
            CodeUtil.searchCompanyName(vo);
            return vo;
        }).collect(Collectors.toList());
        return PageVo.of(res,page.getTotal());
    }

    @LambdaDataScope
    @BuildChildrenRegionWrapper
    public void buildVehicleAccident(LambdaQueryWrapper<VehicleAccidentEval> query,VehicleServiceLifeListReq req) {
        query.like(StrUtil.isNotBlank(req.getCompanyName()), VehicleAccidentEval::getCompanyName, req.getCompanyName())
             .like(StrUtil.isNotBlank(req.getCarNo()), VehicleAccidentEval::getCarNo, req.getCarNo())
             .eq(Objects.nonNull(req.getDangerLevel()), VehicleAccidentEval::getDangerLevel, req.getDangerLevel());
    }

    /**
     * 车辆超速情况列表
     */
    public PageVo<VehicleOverSpeedEvalListVo> vehicleOverSpeedList(VehicleServiceLifeListReq req) {
        LambdaQueryWrapper<VehicleOverSpeedEval> query = Wrappers.lambdaQuery(VehicleOverSpeedEval.class);
        InsuranceRiskEvalManage context = (InsuranceRiskEvalManage) AopContext.currentProxy();
        context.buildVehicleOverSpeed(query,req);
        Page<VehicleOverSpeedEval> page = vehicleOverSpeedEvalService.page(req.page(), query);
        List<VehicleOverSpeedEvalListVo> res = page.getRecords().stream().map(w -> {
            VehicleOverSpeedEvalListVo vo = BeanUtil.copyProperties(w,VehicleOverSpeedEvalListVo.class);
            vo.setRegions(regionsCacheHelper.listParents(w.getRegionId()));
            vo.setDangerLevelName(DangerLevelEnum.getDescByCode(w.getDangerLevel()));
            CodeUtil.searchCompanyName(vo);
            return vo;
        }).collect(Collectors.toList());
        return PageVo.of(res,page.getTotal());
    }
    @LambdaDataScope
    @BuildChildrenRegionWrapper
    public void buildVehicleOverSpeed(LambdaQueryWrapper<VehicleOverSpeedEval> query,VehicleServiceLifeListReq req) {
        query.like(StrUtil.isNotBlank(req.getCompanyName()), VehicleOverSpeedEval::getCompanyName, req.getCompanyName())
             .like(StrUtil.isNotBlank(req.getCarNo()), VehicleOverSpeedEval::getCarNo, req.getCarNo())
             .eq(Objects.nonNull(req.getDangerLevel()), VehicleOverSpeedEval::getDangerLevel, req.getDangerLevel());
    }

    public void vehicleViolationEvalMod(VehicleViolationEvalModReq req) {
        VehicleViolationEval violationEval = BeanUtil.copyProperties(req, VehicleViolationEval.class);
        violationEval.setRemark(StrUtil.nullToEmpty(violationEval.getRemark()));
        violationEval.setUpdateBy(LoginUserUtil.getUserId());
        violationEval.setUpdateOn(LocalDateTime.now());
        boolean update = vehicleViolationEvalService.updateById(violationEval);
        Assert.isTrue(update, "记录不存在");
    }

    public void vehicleAccidentEvalMod(VehicleAccidentEvalModReq req) {
        VehicleAccidentEval accidentEval = BeanUtil.copyProperties(req, VehicleAccidentEval.class);
        accidentEval.setRemark(StrUtil.nullToEmpty(accidentEval.getRemark()));
        accidentEval.setUpdateBy(LoginUserUtil.getUserId());
        accidentEval.setUpdateOn(LocalDateTime.now());
        boolean update = vehicleAccidentEvalService.updateById(accidentEval);
        Assert.isTrue(update, "记录不存在");
    }

    public void vehicleOverSpeedEvalMod(VehicleOverSpeedEvalModReq req) {
        VehicleOverSpeedEval overSpeedEval = BeanUtil.copyProperties(req, VehicleOverSpeedEval.class);
        overSpeedEval.setRemark(StrUtil.nullToEmpty(overSpeedEval.getRemark()));
        overSpeedEval.setUpdateBy(LoginUserUtil.getUserId());
        overSpeedEval.setUpdateOn(LocalDateTime.now());
        boolean update = vehicleOverSpeedEvalService.updateById(overSpeedEval);
        Assert.isTrue(update, "记录不存在");
    }

    public void vehicleViolationEvalDel(Integer id) {
        LambdaQueryWrapper<VehicleViolationEval> wrapper = Wrappers.lambdaQuery(VehicleViolationEval.class);
        InsuranceRiskEvalManage context = (InsuranceRiskEvalManage) AopContext.currentProxy();
        context.buildQuery(wrapper, id);
        VehicleViolationEval violationEval = vehicleViolationEvalService.getOne(wrapper);
        if (Objects.isNull(violationEval)){
            throw new BizException("文件无法删除!");
        }
        vehicleViolationEvalService.removeById(id);
    }

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

    public void vehicleAccidentEvalDel(Integer id) {
        LambdaQueryWrapper<VehicleAccidentEval> wrapper = Wrappers.lambdaQuery(VehicleAccidentEval.class);
        InsuranceRiskEvalManage context = (InsuranceRiskEvalManage) AopContext.currentProxy();
        context.buildAccidentEvalQuery(wrapper, id);
        VehicleAccidentEval accidentEval = vehicleAccidentEvalService.getOne(wrapper);
        if (Objects.isNull(accidentEval)){
            throw new BizException("文件无法删除!");
        }
        vehicleAccidentEvalService.removeById(id);
    }

    @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL)
    public void buildAccidentEvalQuery(LambdaQueryWrapper<VehicleAccidentEval> wrapper, Integer id) {
        wrapper.eq(VehicleAccidentEval::getId,id);
    }

    public void vehicleOverSpeedEvalDel(Integer id) {
        LambdaQueryWrapper<VehicleOverSpeedEval> wrapper = Wrappers.lambdaQuery(VehicleOverSpeedEval.class);
        InsuranceRiskEvalManage context = (InsuranceRiskEvalManage) AopContext.currentProxy();
        context.buildStandardFileQuery(wrapper, id);
        VehicleOverSpeedEval overSpeedEval = vehicleOverSpeedEvalService.getOne(wrapper);
        if (Objects.isNull(overSpeedEval)){
            throw new BizException("文件无法删除!");
        }
        vehicleOverSpeedEvalService.removeById(id);
    }
    @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL)
    public void buildStandardFileQuery(LambdaQueryWrapper<VehicleOverSpeedEval> wrapper, Integer id) {
        wrapper.eq(VehicleOverSpeedEval::getId,id);
    }

    private void importVehicleViolationData(List<VehicleViolationImportDto> importDataList) {
        if (CollectionUtils.isEmpty(importDataList)) {
            return;
        }
        List<VehicleViolationEval> violationEvalList = new ArrayList<>();
        List<String> carNos = CollUtils.fieldList(importDataList, VehicleViolationImportDto::getCarNo);
        Assert.isTrue(carNos.size() == importDataList.size(), "车牌号不可重复");
        Map<String, NdVehicleBaseInfo> carInfoMap = vehicleBaseInfoService.listByCarNo(carNos);
        Assert.isTrue(carNos.size() == carInfoMap.size(), "请确保所有车牌号存在");
        List<Long> companyIds = CollUtils.fieldList(carInfoMap.values(), NdVehicleBaseInfo::getCompanyId);
        Map<Long, Company> companyMap = companyService.listCompanyByIds(companyIds);
        Long userId = LoginUserUtil.getUserId();
        LocalDateTime now = LocalDateTime.now();
        importDataList.forEach(w -> {
            VehicleViolationEval eval = new VehicleViolationEval();
            eval.setCreateBy(userId);
            eval.setCreateOn(now);
            eval.setUpdateBy(userId);
            eval.setUpdateOn(now);
            eval.setViolationCount(w.getViolationCount());
            eval.setRemark(w.getRemark());
            eval.setAvgViolationCount(w.getAvgViolationCount());
            eval.setCarNo(w.getCarNo());
            eval.setMileage(w.getMileage());
            NdVehicleBaseInfo carInfo = carInfoMap.get(w.getCarNo());
            eval.setCarId(carInfo.getId());
            eval.setCompanyId(carInfo.getCompanyId());
            Company company = companyMap.get(eval.getCompanyId());
            eval.setCompanyName(company.getName());
            eval.setRegionId(company.getRegionId());
            eval.setCarFrameNo(w.getChassisNumber());
            eval.setDangerLevel(DangerLevelEnum.getCodeByDesc(w.getRiskEvaluation()));
            violationEvalList.add(eval);
        });
        LambdaQueryWrapper<VehicleViolationEval> delQuery = Wrappers.lambdaQuery(VehicleViolationEval.class)
                .in(VehicleViolationEval::getCarNo, carNos);
        vehicleViolationEvalService.remove(delQuery);
        vehicleViolationEvalService.saveBatch(violationEvalList);
    }

    private void importVehicleOverSpeedData(List<VehicleOverSpeedImportDto> importDataList) {
        if (CollectionUtils.isEmpty(importDataList)) {
            return;
        }
        List<String> carNos = CollUtils.fieldList(importDataList, VehicleOverSpeedImportDto::getCarNo);
        Assert.isTrue(carNos.size() == importDataList.size(), "车牌号不可重复");
        Map<String, NdVehicleBaseInfo> carInfoMap = vehicleBaseInfoService.listByCarNo(carNos);
        Assert.isTrue(carNos.size() == carInfoMap.size(), "请确保所有车牌号存在");
        List<Long> companyIds = CollUtils.fieldList(carInfoMap.values(), NdVehicleBaseInfo::getCompanyId);
        Map<Long, Company> companyMap = companyService.listCompanyByIds(companyIds);
        List<VehicleOverSpeedEval> violationEvalList = new ArrayList<>();
        Long userId = LoginUserUtil.getUserId();
        LocalDateTime now = LocalDateTime.now();
        importDataList.forEach(w -> {
            VehicleOverSpeedEval eval = new VehicleOverSpeedEval();
            eval.setCreateBy(userId);
            eval.setCreateOn(now);
            eval.setUpdateBy(userId);
            eval.setUpdateOn(now);
            eval.setOverSpeedCount(w.getOverSpeedCount());
            eval.setRemark(w.getRemark());
            eval.setAvgOverSpeedCount(w.getAvgOverSpeedCount());
            eval.setCarNo(w.getCarNo());
            eval.setMileage(w.getMileage());
            NdVehicleBaseInfo carInfo = carInfoMap.get(w.getCarNo());
            eval.setCarId(carInfo.getId());
            eval.setCompanyId(carInfo.getCompanyId());
            Company company = companyMap.get(eval.getCompanyId());
            eval.setCompanyName(company.getName());
            eval.setRegionId(company.getRegionId());
            eval.setCarFrameNo(w.getChassisNumber());
            eval.setDangerLevel(DangerLevelEnum.getCodeByDesc(w.getRiskEvaluation()));
            violationEvalList.add(eval);
        });
        LambdaQueryWrapper<VehicleOverSpeedEval> delQuery = Wrappers.lambdaQuery(VehicleOverSpeedEval.class)
                .in(VehicleOverSpeedEval::getCarNo, carNos);
        vehicleOverSpeedEvalService.remove(delQuery);
        vehicleOverSpeedEvalService.saveBatch(violationEvalList);
    }

    private void importVehicleAccidentData(List<VehicleAccidentImportDto> importDataList) {
        if (CollectionUtils.isEmpty(importDataList)) {
            return;
        }
        List<String> carNos = CollUtils.fieldList(importDataList, VehicleAccidentImportDto::getCarNo);
        Assert.isTrue(carNos.size() == importDataList.size(), "车牌号不可重复");
        Map<String, NdVehicleBaseInfo> carInfoMap = vehicleBaseInfoService.listByCarNo(carNos);
        Assert.isTrue(carNos.size() == carInfoMap.size(), "请确保所有车牌号存在");
        List<Long> companyIds = CollUtils.fieldList(carInfoMap.values(), NdVehicleBaseInfo::getCompanyId);
        Map<Long, Company> companyMap = companyService.listCompanyByIds(companyIds);
        List<VehicleAccidentEval> violationEvalList = new ArrayList<>();
        Long userId = LoginUserUtil.getUserId();
        LocalDateTime now = LocalDateTime.now();
        importDataList.forEach(w -> {
            VehicleAccidentEval eval = new VehicleAccidentEval();
            eval.setCreateBy(userId);
            eval.setCreateOn(now);
            eval.setUpdateBy(userId);
            eval.setUpdateOn(now);
            eval.setAccidentCount(w.getAccidentCount());
            eval.setRemark(w.getRemark());
            eval.setAvgAccidentCount(w.getAvgAccidentCount());
            eval.setCarNo(w.getCarNo());
            eval.setMileage(w.getMileage());
            NdVehicleBaseInfo carInfo = carInfoMap.get(w.getCarNo());
            eval.setCarId(carInfo.getId());
            eval.setCompanyId(carInfo.getCompanyId());
            Company company = companyMap.get(eval.getCompanyId());
            eval.setCompanyName(company.getName());
            eval.setRegionId(company.getRegionId());
            eval.setCarFrameNo(w.getChassisNumber());
            eval.setDangerLevel(DangerLevelEnum.getCodeByDesc(w.getRiskEvaluation()));
            violationEvalList.add(eval);
        });
        LambdaQueryWrapper<VehicleAccidentEval> delQuery = Wrappers.lambdaQuery(VehicleAccidentEval.class)
                .in(VehicleAccidentEval::getCarNo, carNos);
        vehicleAccidentEvalService.remove(delQuery);
        vehicleAccidentEvalService.saveBatch(violationEvalList);
    }

    private void importOutDangerData(List<OutDangerImportDto> importDataList) {
        if (CollectionUtils.isEmpty(importDataList)) {
            return;
        }
        List<String> carNos = CollUtils.fieldList(importDataList, OutDangerImportDto::getCarNo);
        // Assert.isTrue(carNos.size() == importDataList.size(), "车牌号不可重复");
        Map<String, NdVehicleBaseInfo> carInfoMap = vehicleBaseInfoService.listByCarNo(carNos);
        Assert.isTrue(carNos.size() == carInfoMap.size(), "请确保所有车牌号存在");
        List<Long> companyIds = CollUtils.fieldList(carInfoMap.values(), NdVehicleBaseInfo::getCompanyId);
        Map<Long, Company> companyMap = companyService.listCompanyByIds(companyIds);
        Map<Long, NdInsureInfo> insureCompanyInfoMap = insureInfoService.listInsureCompanyByCompanyIds(companyIds);

        List<NdInsureOutDanger> ndInsureOutDangers = new ArrayList<>();
        Long userId = LoginUserUtil.getUserId();
        LocalDateTime now = LocalDateTime.now();
        importDataList.forEach(w -> {
            NdInsureOutDanger eval = new NdInsureOutDanger();
            eval.setCreateBy(userId);
            eval.setCreateOn(now);
            eval.setUpdateBy(userId);
            eval.setUpdateOn(now);

            NdVehicleBaseInfo carInfo = carInfoMap.get(w.getCarNo());
            Company company = companyMap.get(carInfo.getCompanyId());

            DateTime parse = DateUtil.parse(w.getAccidentTime());
            Instant instant = parse.toInstant();
            ZoneId zoneId = ZoneId.systemDefault();
            LocalDateTime accidentTime = instant.atZone(zoneId).toLocalDateTime();

            eval.setAccidentTime(accidentTime);
            eval.setAccidentAddress(w.getAccidentAddress());
            eval.setCompanyId(company.getId());
            eval.setCompanyName(company.getName());
            eval.setRegionId(company.getRegionId());
            eval.setRegionName(company.getName());
            eval.setCarPlate(w.getCarNo());
            if (insureCompanyInfoMap.size() == 0){
                eval.setInsureCompany(null);
            }else {
                NdInsureInfo ndInsureInfo = insureCompanyInfoMap.get(carInfo.getCompanyId());
                eval.setInsureCompany(ndInsureInfo.getInsureCompany());
            }
            eval.setInjuries(w.getInjuries());
            eval.setDeathToll(w.getDeathToll());
            eval.setCompensateAmount(w.getCompensateAmount());

            ndInsureOutDangers.add(eval);
        });

        // 筛选出不在出险信息表中的数据，进行导入
        List<NdInsureOutDanger> insureOutDangers = ndInsureOutDangers.stream().filter(w -> {
            NdInsureOutDanger ndInsureOutDanger = ndInsureOutDangerService.getOne(Wrappers.lambdaQuery(NdInsureOutDanger.class)
                    .eq(NdInsureOutDanger::getCarPlate, w.getCarPlate())
                    .eq(NdInsureOutDanger::getInsureCompany,w.getInsureCompany())
                    .eq(NdInsureOutDanger::getCompanyName,w.getCompanyName())
                    .eq(NdInsureOutDanger::getAccidentAddress,w.getAccidentAddress())
                    .eq(NdInsureOutDanger::getAccidentTime,w.getAccidentTime())
                    .eq(NdInsureOutDanger::getInjuries,w.getInjuries())
                    .eq(NdInsureOutDanger::getDeathToll,w.getDeathToll())
                    .eq(NdInsureOutDanger::getCompensateAmount,w.getCompensateAmount()));
            if (Objects.isNull(ndInsureOutDanger)){
                return true;
            }
            return false;
        }).collect(Collectors.toList());

        if (CollUtil.isEmpty(insureOutDangers)){
            throw new BizException("导入数据均已存在，无需重复导入!");
        }

        LambdaQueryWrapper<NdInsureOutDanger> delQuery = Wrappers.lambdaQuery(NdInsureOutDanger.class)
                .in(NdInsureOutDanger::getCarPlate, carNos);
        ndInsureOutDangerService.remove(delQuery);
        ndInsureOutDangerService.saveBatch(insureOutDangers);
    }

    @Transactional(rollbackFor = Exception.class)
    public void importTemplateData(ImportTemplateEnum template, MultipartFile file) {
        String contentType = file.getContentType();
        if (!contentType.equals(ExcelUtil.XLS_CONTENT_TYPE) &&
                !contentType.equals(ExcelUtil.XLSX_CONTENT_TYPE)
        ) {
            throw BizException.wrap("导入失败,不支持的文件类型,请按照提供的模板导入文件!");
        }
        try (InputStream inputStream = file.getInputStream();
                ExcelReader reader = ExcelUtil.getReader(inputStream)) {
            Map<String, String> alias;
            List<String> title = ImportTemplateConstant.getTemplateTitle(template);
            switch (template) {
                case VEHICLE_VIOLATION:
                    alias = new HashMap<>(title.size());
                    alias.put(title.get(0), "id");
                    alias.put(title.get(1), "city");
                    alias.put(title.get(2), "zone");
                    alias.put(title.get(3), "companyName");
                    alias.put(title.get(4), "carNo");
                    alias.put(title.get(5), "chassisNumber");
                    alias.put(title.get(6), "mileage");
                    alias.put(title.get(7), "violationCount");
                    alias.put(title.get(8), "avgViolationCount");
                    alias.put(title.get(9), "riskEvaluation");
                    alias.put(title.get(10), "remark");
                    reader.setHeaderAlias(alias);
                    importVehicleViolationData(reader.readAll(VehicleViolationImportDto.class));
                    break;
                case VEHICLE_ACCIDENT:
                    alias = new HashMap<>(title.size());
                    alias.put(title.get(0), "id");
                    alias.put(title.get(1), "city");
                    alias.put(title.get(2), "zone");
                    alias.put(title.get(3), "companyName");
                    alias.put(title.get(4), "carNo");
                    alias.put(title.get(5), "chassisNumber");
                    alias.put(title.get(6), "mileage");
                    alias.put(title.get(7), "accidentCount");
                    alias.put(title.get(8), "avgAccidentCount");
                    alias.put(title.get(9), "riskEvaluation");
                    alias.put(title.get(10), "remark");
                    reader.setHeaderAlias(alias);
                    importVehicleAccidentData(reader.readAll(VehicleAccidentImportDto.class));
                    break;
                case VEHICLE_OVER_SPEED:
                    alias = new HashMap<>(title.size());
                    alias.put(title.get(0), "id");
                    alias.put(title.get(1), "city");
                    alias.put(title.get(2), "zone");
                    alias.put(title.get(3), "companyName");
                    alias.put(title.get(4), "carNo");
                    alias.put(title.get(5), "chassisNumber");
                    alias.put(title.get(6), "mileage");
                    alias.put(title.get(7), "overSpeedCount");
                    alias.put(title.get(8), "avgOverSpeedCount");
                    alias.put(title.get(9), "riskEvaluation");
                    alias.put(title.get(10), "remark");
                    reader.setHeaderAlias(alias);
                    importVehicleOverSpeedData(reader.readAll(VehicleOverSpeedImportDto.class));
                    break;
                case INSURE_OUT_DANGER:
                    alias = new HashMap<>(title.size());
                    alias.put(title.get(0), "id");
                    alias.put(title.get(1), "regionName");
                    alias.put(title.get(2), "carNo");
                    alias.put(title.get(3), "insureCompany");
                    alias.put(title.get(4), "companyName");
                    alias.put(title.get(5), "accidentAddress");
                    alias.put(title.get(6), "accidentTime");
                    alias.put(title.get(7), "injuries");
                    alias.put(title.get(8), "deathToll");
                    alias.put(title.get(9), "compensateAmount");
                    reader.setHeaderAlias(alias);
                    importOutDangerData(reader.readAll(OutDangerImportDto.class));
                    break;
                default:
                    throw new BizException("不支持的数据导入类型");
            }
} catch (IOException e) {
        throw new RuntimeException(e);
        }
    }
}
