package com.taais.biz.service.impl;

import java.util.Date;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.taais.biz.constant.BizConstant;
import com.taais.biz.domain.Data;
import com.taais.biz.domain.DataAmplificationTask;
import com.taais.biz.domain.bo.DataAmplificationTaskBo;
import com.taais.biz.domain.bo.DataBo;
import com.taais.biz.domain.vo.BatchDataResult;
import com.taais.biz.domain.dto.DataAmplifyDto;
import com.taais.biz.domain.vo.DataAmplificationTaskVo;
import com.taais.biz.domain.vo.DataSelectVo;
import com.taais.biz.domain.vo.DataVo;
import com.taais.biz.mapper.DataMapper;
import com.taais.biz.service.IDataAmplificationTaskService;
import com.taais.biz.service.IDataService;
import com.taais.common.core.config.TaaisConfig;
import com.taais.common.core.core.domain.CommonResult;
import com.taais.common.core.core.page.PageResult;
import com.taais.common.core.utils.MapstructUtils;
import com.taais.common.core.utils.StringUtils;
import com.taais.common.core.utils.file.FileUploadUtils;
import com.taais.common.core.utils.file.FileUtils;
import com.taais.common.core.utils.file.UnPackedUtil;
import com.taais.common.json.utils.JsonUtils;
import com.taais.common.orm.core.page.PageQuery;
import com.taais.common.orm.core.service.impl.BaseServiceImpl;
import com.taais.common.redis.utils.RedisUtils;
import com.taais.system.domain.vo.SysDictDataVo;
import com.taais.system.service.ISysDictDataService;
import jakarta.annotation.Resource;
import net.lingala.zip4j.model.FileHeader;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.Instant;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static com.taais.biz.domain.table.DataTableDef.DATA;

/**
 * 数据管理Service业务层处理
 *
 * @author km
 * 2024-04-22
 */
@Service
public class DataServiceImpl extends BaseServiceImpl<DataMapper, Data> implements IDataService {

    public static final String FORM_SELECTS_KEY = "taais:biz:demo:data:formSelect:";
    private static final Logger log = LoggerFactory.getLogger(DataServiceImpl.class);
    private static final String ZIP = ".zip";
    private static final String RAR = ".rar";
    private static final String TXT = ".txt";
    private static final String[] VALID_EXTENSIONS = {".jpg", ".jpeg", ".png", ".bmp"};
    private static final String RESULT_CODE = "status";
    private static final String RESULT_STATUS = "200";
    private static final String AMPLIFY = "/AMPLIFY/";
    @Resource
    private DataMapper dataMapper;

    @Resource
    private IDataAmplificationTaskService dataAmplificationTaskService;

    @Resource
    private ISysDictDataService dictDataService;

    @Override
    public QueryWrapper query() {
        return super.query().from(DATA);
    }

    private QueryWrapper buildQueryWrapper(DataBo dataBo) {
        QueryWrapper queryWrapper = super.buildBaseQueryWrapper();
        queryWrapper.and(DATA.NAME.like
            (dataBo.getName()));
//        queryWrapper.and(DATA.DATA_TYPE.eq
//                (dataBo.getDataType()));
//        queryWrapper.and(DATA.FILE_TYPE.eq
//                (dataBo.getFileType()));
        queryWrapper.and(DATA.OBJECT_TYPE.eq
            (dataBo.getObjectType()));
        queryWrapper.and(DATA.OBJECT_SUBTYPE.eq
            (dataBo.getObjectSubtype()));
        queryWrapper.and(DATA.BATCH_NUM.eq
            (dataBo.getBatchNum()));
        queryWrapper.and(DATA.SCENE.eq
            (dataBo.getScene()));
        queryWrapper.and(DATA.DATA_SOURCE.eq
            (dataBo.getDataSource()));
        queryWrapper.and(DATA.GATHER_TIME.eq
            (dataBo.getGatherTime()));
        queryWrapper.and(DATA.GATHER_SPOT.eq
            (dataBo.getGatherSpot()));
        queryWrapper.and(DATA.URL.eq
            (dataBo.getUrl()));
        queryWrapper.and(DATA.LABELURL.eq
            (dataBo.getLabelurl()));
//        queryWrapper.and(DATA.INCREMENT.eq
//                (dataBo.getIncrement()));
        queryWrapper.and(DATA.LABELED.eq
            (dataBo.getLabeled()));
//        queryWrapper.orderBy(DATA.CREATE_TIME.desc());
        return queryWrapper;
    }

    @Override
    public List<BatchDataResult> batchSelect() {
        return dataMapper.getBatchData();
    }

    /**
     * 查询数据管理
     *
     * @param id 数据管理主键
     * @return 数据管理
     */
    @Override
    public DataVo selectById(Long id) {
        return this.getOneAs(query().where(DATA.ID.eq(id)), DataVo.class);
    }

    public List<DataVo> getDataByBatchNum(String batchNum) {
        return this.listAs(query().where(DATA.BATCH_NUM.eq(batchNum)), DataVo.class);
    }

    /**
     * 查询数据管理列表
     *
     * @param dataBo 数据管理Bo
     * @return 数据管理集合
     */
    @Override
    public List<DataVo> selectList(DataBo dataBo) {
        QueryWrapper queryWrapper = buildQueryWrapper(dataBo);
        return this.listAs(queryWrapper, DataVo.class);
    }

    @Override
    @Transactional
    public CommonResult<Boolean> uploadDataInfo(MultipartFile file, Data dataInfo) {
        //1.检测是否有重复的批次号
        QueryWrapper query = query();
        query.eq(Data::getBatchNum, dataInfo.getBatchNum());
        long count = dataMapper.selectCountByQuery(query);
        if (count > 0) {
            return CommonResult.fail("检测出重复批次号，请仔细检查后重新导入！");
        }
        try {
            Boolean labeled = dataInfo.getLabeled();
            //2.解压图片并检查
            String originalFilename = file.getOriginalFilename();
            assert originalFilename != null;
            String suffix = StringUtils.substring(originalFilename, originalFilename.lastIndexOf("."), originalFilename.length());
            // 解压
            String basedir = TaaisConfig.getUploadPath();
            // 解压目录
            File zipOrRarTemp = FileUploadUtils.getAbsoluteFile(basedir, FileUploadUtils.extractFilename2(file));
            String destZip = zipOrRarTemp.getAbsolutePath();
            file.transferTo(Paths.get(destZip));
            String dest = zipOrRarTemp.getParent();
            // 解压图片集合
            List<File> extractedImagesFileList = new ArrayList<>();
            if (ZIP.equals(suffix)) {
                //添加解压目录
                for (FileHeader fileHeader : UnPackedUtil.unPackZip(zipOrRarTemp, dest)) {
                    initFileInfo(dest, extractedImagesFileList, fileHeader.isDirectory(), fileHeader.getFileName());
                }
            } else if (RAR.equals(suffix)) {
                //添加解压目录
                for (com.github.junrar.rarfile.FileHeader fileHeader : UnPackedUtil.unPackRar(zipOrRarTemp, dest)) {
                    initFileInfo(dest, extractedImagesFileList, fileHeader.isDirectory(), fileHeader.getFileName());
                }
            } else {
                return CommonResult.fail("请上传.zip、.rar压缩文件。！");
            }

            //检测图片文件是否为空
            if (extractedImagesFileList.isEmpty()) {
                return CommonResult.fail("压缩文件图片为空，请检查后重新上传！");
            }

            //3获取ID集合
            List<Long> ids = dataMapper.getIds(extractedImagesFileList.size());
            if (ids.isEmpty()) {
                return CommonResult.fail("系统异常！");
            }

            List<Boolean> labeledList = new ArrayList<>();
            List<Data> dataList = new ArrayList<>();
            AtomicInteger countSize = new AtomicInteger();
            List<Data> finalDataList = dataList;
            extractedImagesFileList.forEach(fileInfo -> {
                //获取ID
                Long id = ids.get(countSize.get());
                Data data = new Data();
                //拷贝dataInfo
                BeanUtils.copyProperties(dataInfo, data);
                //检测是否标注
                if (checkLabeled(fileInfo.getPath())) {
                    labeledList.add(Boolean.TRUE);
                    data.setLabeled(Boolean.TRUE);
                } else {
                    labeledList.add(Boolean.FALSE);
                    data.setLabeled(Boolean.FALSE);
                }
                try {
                    Path path = Paths.get(fileInfo.getAbsolutePath());
                    // 使用Files类的readAttributes方法获取文件的基本属性
                    BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
                    // 获取文件的修改时间
                    Instant creationTime = attrs.lastModifiedTime().toInstant();
                    // 将Instant转换为Date
                    Date date = Date.from(creationTime);
                    //设置文件创建时间
                    data.setId(id);
                    data.setGatherTime(date);
                    data.setName(fileInfo.getName());
                    //更改图片文件名称
                    String fileHeaderSuffix = StringUtils.substring(fileInfo.getName(), fileInfo.getName().lastIndexOf("."), fileInfo.getName().length());
                    String destInfo = fileInfo.getPath().replaceAll(fileInfo.getName(), "");
                    File newFile = new File(destInfo, id + fileHeaderSuffix);
                    File odlFile = new File(destInfo, fileInfo.getName());
                    log.info("更改用户上传图片文件名称:{}", odlFile.renameTo(newFile));
                    String imagePath = FileUploadUtils.getPathFileName(destInfo, id + fileHeaderSuffix);
                    data.setUrl(imagePath);
                    //该图片有标注，更改标注文件名称
                    if (data.getLabeled()) {
                        String labeledPath = fileInfo.getPath().replaceFirst("[.][^.]+$", "") + ".txt";
                        File labeledNewFile = new File(destInfo, id + ".txt");
                        File labeledOdlFile = new File(labeledPath);
                        log.info("更改用户上传标注文件名称:{}", labeledOdlFile.renameTo(labeledNewFile));
                        String labelUrl = FileUploadUtils.getPathFileName(destInfo, id + ".txt");
                        data.setLabelurl(labelUrl);
                    }
                    finalDataList.add(data);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                countSize.getAndIncrement();
            });
            // TODO 李兆晏 确认逻辑是否正确 start
//            //是否选择已标注，如果已标注则需要检测所有图片是否标注
//            if (!labeledList.isEmpty()) {
//                // 已标注数量
//                long unmarkedCount = labeledList.stream().filter(Boolean.FALSE::equals).count();
//                // 未标注数量
//                long markedCount = labeledList.stream().filter(Boolean.TRUE::equals).count();
//                // 如果存在未标注的数据，则返回错误信息
//                if (unmarkedCount > 0 && labeled) {
//                    String format = String.format("错误: 已标注文件 %d 个，未标注文件 %d 个", markedCount, unmarkedCount);
//                    return CommonResult.fail(format);
//                }
//                // 如果存在标注的数据，则返回错误信息
//                if (markedCount > 0 && !labeled) {
//                    String format = String.format("错误: 已标注文件 %d 个，未标注文件 %d 个", markedCount, unmarkedCount);
//                    return CommonResult.fail(format);
//                }
//            }
            if (labeled) {
                // 未标注数量
                long unmarkedCount = labeledList.stream().filter(Boolean.FALSE::equals).count();
                // 已标注数量
                long markedCount = labeledList.stream().filter(Boolean.TRUE::equals).count();

                if (unmarkedCount > 0) {
                    String format = String.format("错误: 已标注文件 %d 个，未标注文件 %d 个", markedCount, unmarkedCount);
                    return CommonResult.fail(format);
                }
            }
            // TODO 李兆晏 确认逻辑是否正确 end

            int batchSize = 100;
            int totalSize = dataList.size();
            int page = (int) Math.ceil((double) totalSize / batchSize); // 计算总批次数

            for (int i = 0; i < page; i++) {
                int fromIndex = i * batchSize;
                int toIndex = Math.min(fromIndex + batchSize, totalSize); // 确保最后一批不越界
                List<Data> batchList = new ArrayList<>(dataList.subList(fromIndex, toIndex)); // 生成子列表副本
                dataMapper.insertBatch(batchList); // 批量插入
            }
            FileUtils.deleteFile(destZip);
        } catch (Exception e) {
            log.error("[uploadDataInfo]数据集处理出现未知异常.e:", e);
            return CommonResult.fail("系统异常！");
        }
        return CommonResult.success("数据集上传成功！");
    }

    @Override
    @Transactional
    public CommonResult<Boolean> dataAmplify(DataAmplifyDto dataAmplifyDto) {
        DataAmplificationTaskBo dataAmplificationTaskBo = new DataAmplificationTaskBo();
        dataAmplificationTaskBo.setName(dataAmplifyDto.getTaskName());
        dataAmplificationTaskBo.setStatus(BizConstant.TASK_STATUS_PENDING);
        dataAmplificationTaskBo.setDataBatchNums(dataAmplifyDto.getBatchNum());
        dataAmplificationTaskBo.setAugmentationType(dataAmplifyDto.getAugmentationType());
        dataAmplificationTaskBo.setParameters(JsonUtils.toJsonString(dataAmplifyDto.getOtherParams()));
        dataAmplificationTaskBo.setDelFlag(0);
        DataAmplificationTask insertedTask = dataAmplificationTaskService.insertTask(dataAmplificationTaskBo);
        return this.amplifyForData(insertedTask.getId().toString());
    }

    private void initFileInfo(String dest, List<File> extractedImagesFileList, boolean directory, String fileName) {
        if (!directory) {
            String fileHeaderSuffix = StringUtils.substring(fileName, fileName.lastIndexOf("."), fileName.length());
            if (Arrays.asList(VALID_EXTENSIONS).contains(fileHeaderSuffix)) {
                extractedImagesFileList.add(new File(dest, fileName));
            }
        }
    }

    private boolean checkLabeled(String pathFileName) {
        Path newPath = Paths.get(pathFileName.replaceFirst("[.][^.]+$", "") + ".txt");
        // 检查替换后的文件是否存在
        boolean exists = Files.exists(newPath);
        log.info("[checkLabeled]图片文件路径名称:{},标注文件路径名称:{},是否标注:{}", pathFileName, newPath, exists);
        return exists;
    }

    /**
     * 分页查询数据管理列表
     *
     * @param dataBo 数据管理Bo
     * @return 分页数据管理集合
     */
    @Override
    public PageResult<DataVo> selectPage(DataBo dataBo) {
        QueryWrapper queryWrapper = buildQueryWrapper(dataBo);
        Page<DataVo> page = this.pageAs(PageQuery.build(), queryWrapper, DataVo.class);
        return PageResult.build(page);
    }

    /**
     * 新增数据管理
     *
     * @param dataBo 数据管理Bo
     * @return 结果:true 操作成功，false 操作失败
     */
    @Override
    public boolean insert(DataBo dataBo) {
        Data data = MapstructUtils.convert(dataBo, Data.class);
        //新增之后清除缓存
        deleteFormSelectKey();
        return this.save(data);//使用全局配置的雪花算法主键生成器生成ID值
    }

    private void deleteFormSelectKey() {
//        RedisUtils.deleteKeys(); 方法不知道为什么失效
        String[] keys = {"increment",
            "scene",
            "data_source",
            "object_type",
            "batch_num",
            "object_subtype",
            "gather_spot"};
        RedissonClient client = RedisUtils.getClient();
        for (String key : keys) {
            client.getBucket(FORM_SELECTS_KEY + key).delete();
        }
    }

    /**
     * 修改数据管理
     *
     * @param dataBo 数据管理Bo
     * @return 结果:true 更新成功，false 更新失败
     */
    @Override
    public boolean update(DataBo dataBo) {
        Data data = MapstructUtils.convert(dataBo, Data.class);
        if (ObjectUtil.isNotNull(data) && ObjectUtil.isNotNull(data.getId())) {
            // 不更新采集时间
            data.setGatherTime(null);
            boolean updated = this.updateById(data);
            //新增之后清除缓存
            deleteFormSelectKey();
            return updated;
        }
        //新增之后清除缓存
        deleteFormSelectKey();
        return false;
    }

    /**
     * 批量删除数据管理
     *
     * @param ids 需要删除的数据管理主键集合
     * @return 结果:true 删除成功，false 删除失败
     */
//    @Transactional
    @Override
    public boolean deleteByIds(Long[] ids) {
        QueryWrapper queryWrapper = QueryWrapper.create().from(DATA).where(DATA.ID.in(Arrays.asList(ids)));
        //新增之后清除缓存
        deleteFormSelectKey();
        return this.remove(queryWrapper);
    }

    @Override
    public List<Data> selectByIds(List<Long> ids) {
        return this.listByIds(ids);
    }

    @Override
    public List<DataSelectVo> getFormSelects(String field) {
        String cacheKey = FORM_SELECTS_KEY + field;
        List<DataSelectVo> cacheList = RedisUtils.getCacheList(cacheKey);
        if (cacheList == null || cacheList.isEmpty()) {
            cacheList = dataMapper.getFormSelects(field);
            RedisUtils.setCacheList(cacheKey, cacheList);
//            RedisUtils.expire(cacheKey, 60);
        }
        return cacheList;
    }

    @Override
    @Transactional
    public CommonResult<Boolean> amplifyForData(String id) {
        DataAmplificationTaskVo taskVo = dataAmplificationTaskService.selectById(Long.valueOf(id));
        DataAmplifyDto dataAmplifyDto = new DataAmplifyDto();
        dataAmplifyDto.setId(taskVo.getId().toString());
        dataAmplifyDto.setAugmentationType(taskVo.getAugmentationType());
        List<Map<String, String>> maps = JsonUtils.parseArray(taskVo.getParameters(), Map.class);
        dataAmplifyDto.setOtherParams(maps);
        dataAmplifyDto.setBatchNum(taskVo.getDataBatchNums());
        return this.doAmplify(dataAmplifyDto);
    }

    private CommonResult<Boolean> doAmplify(DataAmplifyDto dataAmplifyDto) {
        this.updateEmp(Long.valueOf(dataAmplifyDto.getId()));
        String[] split = dataAmplifyDto.getBatchNum().split(",");
        SysDictDataVo sysDictDataVo = dictDataService.selectDictDataByTypeAndLabel("python_api_address", "python_expand_data");

        for (String batchNum : split) {
            QueryWrapper query = query();
            query.eq(Data::getBatchNum, batchNum);
            List<Data> dataList = dataMapper.selectListByQuery(query);
            if (dataList.isEmpty()) {
                this.updateFail(Long.valueOf(dataAmplifyDto.getId()));
                continue;
            }

            List<Data> dataListInfo = dataList.stream().filter(data -> !StringUtils.isEmpty(data.getUrl())).toList();
            if (dataListInfo.isEmpty()) {
                this.updateFail(Long.valueOf(dataAmplifyDto.getId()));
                continue;
            }
            String filePath = TaaisConfig.getUploadPath();
            LocalDate currentDate = LocalDate.now();
            // 定义日期格式器
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
            String formattedDate = currentDate.format(formatter);
            filePath = filePath + File.separator + formattedDate;
            String finalFilePath = filePath;
            Map<String, String> otherParams = new HashMap<>();
            for (Map<String, String> param : dataAmplifyDto.getOtherParams()) {
                otherParams.put(param.get("agName"), param.get("defaultValue"));
            }
            dataListInfo.forEach(dataInfo -> {
                try {
                    boolean success = true;
                    String message = "";
                    Date startTime = new Date();

                    //循环调用Python扩增接口
                    Map<String, Object> bodyJson = new HashMap<>();
                    bodyJson.put("bizType", "数据扩增");
                    bodyJson.put("bizId", dataAmplifyDto.getId());
                    bodyJson.put("augmentationType", dataAmplifyDto.getAugmentationType());
                    bodyJson.put("inputImagePath", dataInfo.getUrl());
                    String outputImagePath = finalFilePath + AMPLIFY + System.currentTimeMillis();
                    File desc = new File(outputImagePath);
                    if (!desc.exists()) {
                        log.info("创建文件目录: {}", desc.mkdirs());
                    }
                    bodyJson.put("outputImagePath", outputImagePath);
                    bodyJson.put("otherParams", otherParams);
                    String logPath = TaaisConfig.getProfile() + "/task/log/" + dataAmplifyDto.getId() + "_log.log";
                    System.out.println("logPath===>" + logPath);
                    bodyJson.put("logPath", logPath);
                    //实际请求接口，接口未提供，暂且注释
                    String response = HttpRequest.post(sysDictDataVo.getDictValue())
                        .body(JsonUtils.toJsonString(bodyJson))
                        .execute().body();
//                String response = "{\"status\":200,\"msg\":\"扩增成功\"}";
                    ObjectMapper objectMapper = new ObjectMapper();
                    JsonNode rootNode = objectMapper.readTree(response);
                    String resultCode = rootNode.path(RESULT_CODE).asText();
                    //判断接口是否响应成功
                    if (!RESULT_STATUS.equals(resultCode)) {
                        success = false;
                    }
                    message = rootNode.path("msg").asText();
                    //处理当前目录文件，并进行入库
                    saveDataInfo(outputImagePath, dataInfo);

                    DataAmplificationTaskVo taskVo = dataAmplificationTaskService.selectById(Long.valueOf(dataAmplifyDto.getId()));
                    Date endTime = new Date();
                    DataAmplificationTaskBo update = new DataAmplificationTaskBo();
                    if (taskVo.getInputImagePath() != null) {
                        update.setInputImagePath(taskVo.getInputImagePath() + "|" + dataInfo.getUrl());
                    } else {
                        update.setInputImagePath(dataInfo.getUrl());
                    }
                    if (taskVo.getOutputImagePath() != null) {
                        update.setOutputImagePath(taskVo.getOutputImagePath() + "|" + outputImagePath);
                    } else {
                        update.setOutputImagePath(outputImagePath);
                    }
                    update.setId(Long.valueOf(dataAmplifyDto.getId()));
                    update.setStartTime(startTime);
                    update.setEndTime(endTime);
                    update.setCostSecond((int) (endTime.getTime() - startTime.getTime()));
                    update.setStatus(success ? BizConstant.TASK_STATUS_SUCCEED : BizConstant.TASK_STATUS_FAILED);
                    update.setLog(taskVo.getLog() + "|" + message);
                    update.setVersion(taskVo.getVersion());
                    update.setRemarks(taskVo.getRemarks() + "|" + (int) (endTime.getTime() - startTime.getTime()));
                    dataAmplificationTaskService.update(update);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });
        }
        //根据批次号获取该批次的所有文件数据
        return CommonResult.success();
    }

    private void updateFail(Long id) {
        DataAmplificationTaskVo taskVo = dataAmplificationTaskService.selectById(id);
        DataAmplificationTaskBo update = new DataAmplificationTaskBo();
        update.setId(taskVo.getId());
        update.setStatus(BizConstant.TASK_STATUS_FAILED);
        update.setLog(taskVo.getLog() + "|" + "该批次下没有文件数据，请重新选择批次！");
        update.setVersion(taskVo.getVersion());
        dataAmplificationTaskService.update(update);
    }

    private void updateEmp(Long id) {
        DataAmplificationTaskVo taskVo = dataAmplificationTaskService.selectById(id);
        DataAmplificationTaskBo update = new DataAmplificationTaskBo();
        update.setOutputImagePath("");
        update.setInputImagePath("");
        update.setId(id);
        update.setLog("");
        update.setVersion(taskVo.getVersion());
        update.setRemarks("");
        dataAmplificationTaskService.update(update);
    }

    /**
     * 解析目标目录所有文件，进行文件更名并入库
     *
     * @param directoryPath：目录地址
     * @param dataInfo：深拷贝对象
     */
    public void saveDataInfo(String directoryPath, Data dataInfo) {
        try {
            // 获取指定目录下所有文件
            File directory = new File(directoryPath);
            List<File> extractedImagesFileList = new ArrayList<>();
            if (directory.exists() && directory.isDirectory()) {
                File[] files = directory.listFiles();
                if (files != null) {
                    for (File file : files) {
                        initFileInfo(directoryPath, extractedImagesFileList, file.isDirectory(), file.getName());
                    }
                }
            }

            // 获取ID集合
            List<Long> ids = dataMapper.getIds(extractedImagesFileList.size());
            if (ids.isEmpty()) {
                return;
            }

            List<Data> dataList = new ArrayList<>();
            AtomicInteger countSize = new AtomicInteger();
            extractedImagesFileList.forEach(fileInfo -> {
                Long id = ids.get(countSize.get());
                Data data = new Data();
                BeanUtils.copyProperties(dataInfo, data);

                if (checkLabeled(fileInfo.getPath())) {
                    data.setLabeled(Boolean.TRUE);
                } else {
                    data.setLabeled(Boolean.FALSE);
                }

                try {
                    Path path = Paths.get(fileInfo.getAbsolutePath());
                    BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
                    Instant creationTime = attrs.lastModifiedTime().toInstant();
                    Date date = Date.from(creationTime);

                    data.setId(id);
                    data.setGatherTime(date);
                    data.setName(fileInfo.getName());

                    // 更改图片文件名称
                    String fileHeaderSuffix = StringUtils.substring(fileInfo.getName(), fileInfo.getName().lastIndexOf("."), fileInfo.getName().length());
                    String destInfo = fileInfo.getPath().replaceAll(fileInfo.getName(), "");
                    File newFile = new File(destInfo, id + fileHeaderSuffix);
                    File oldFile = new File(destInfo, fileInfo.getName());
                    log.info("saveDataInfo更改用户上传图片文件名称:{}", oldFile.renameTo(newFile));

                    String imagePath = FileUploadUtils.getPathFileName(destInfo, id + fileHeaderSuffix);
                    data.setUrl(imagePath);

                    if (data.getLabeled()) {
                        String labeledPath = fileInfo.getPath().replaceFirst("[.][^.]+$", "") + ".txt";
                        File labeledNewFile = new File(destInfo, id + ".txt");
                        File labeledOldFile = new File(labeledPath);
                        log.info("saveDataInfo更改用户上传标注文件名称:{}", labeledOldFile.renameTo(labeledNewFile));
                        String labelUrl = FileUploadUtils.getPathFileName(destInfo, id + ".txt");
                        data.setLabelurl(labelUrl);
                    }
                    dataList.add(data);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                countSize.getAndIncrement();
            });

            dataMapper.insertBatch(dataList);
        } catch (Exception e) {
            log.error("[saveDataInfo]数据集处理出现未知异常.e:", e);
        }
    }

}
