/*
* Copyright (c) 京北方信息技术股份有限公司 Corporation 2022 . All rights reserved.
*
*/
package net.northking.cctp.dataPool.api.dataSets.service;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.page.PageMethod;
import net.northking.cctp.common.cache.EntityNameCache;
import net.northking.cctp.common.cache.EntityNameCatalog;
import net.northking.cctp.common.db.BasicService;
import net.northking.cctp.common.db.DefaultPagination;
import net.northking.cctp.common.db.OrderBy;
import net.northking.cctp.common.db.Pagination;
import net.northking.cctp.common.db.annotation.DatabaseReadOnly;
import net.northking.cctp.common.db.excel.AbstractExcelService;
import net.northking.cctp.common.db.excel.ExcelHeader;
import net.northking.cctp.common.dto.CpLogAddDto;
import net.northking.cctp.common.enums.FileBusinessTypeEnum;
import net.northking.cctp.common.exception.PlatformRuntimeException;
import net.northking.cctp.common.feign.MonsterLogServer;
import net.northking.cctp.common.http.QueryByPage;
import net.northking.cctp.common.s3.FileDownloadException;
import net.northking.cctp.common.s3.FileUploadException;
import net.northking.cctp.common.s3.NKFile;
import net.northking.cctp.common.s3.SimpleStorageService;
import net.northking.cctp.common.security.authentication.NKSecurityContext;
import net.northking.cctp.common.util.UUIDUtil;
import net.northking.cctp.dataPool.bus.LogRabbitMQPublisher;
import net.northking.cctp.dataPool.db.entity.DataSetEnvRel;
import net.northking.cctp.dataPool.db.entity.DataSetTree;
import net.northking.cctp.dataPool.db.entity.DataSets;
import net.northking.cctp.dataPool.db.service.DataSetEnvRelService;
import net.northking.cctp.dataPool.db.service.DataSetTreeService;
import net.northking.cctp.dataPool.db.service.DataSetsService;
import net.northking.cctp.dataPool.dto.dataSets.*;
import net.northking.cctp.dataPool.enums.DataHeaderType;
import net.northking.cctp.dataPool.enums.DataPoolError;
import net.northking.cctp.dataPool.feign.AttachmentFeignClient;
import net.northking.cctp.dataPool.feign.ProjectFeignClient;
import net.northking.cctp.dataPool.feign.ScriptFeignClient;
import net.northking.cctp.dataPool.feign.dto.AtuInputDataSetResultDto;
import net.northking.cctp.dataPool.utils.ExcelUtils;
import net.northking.cctp.dataPool.utils.MinioPathUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 数据集服务实现类
 *
 * @author maven-cctp-plugin
 * @since 1.0
 */

@Service
@ConditionalOnMissingBean(name = "DataSetsApiServiceImpl")
public class DataSetsApiServiceImpl extends AbstractExcelService<DataSets> implements DataSetsApiService
{
  /**
   * 日志
   */
  private final static Logger logger = LoggerFactory.getLogger(DataSetsApiServiceImpl.class);

  @Autowired
  private DataSetsService dataSetsService;
  @Autowired
  private DataSetTreeService dataSetTreeService;
  @Autowired
  private DataSetEnvRelService dataSetEnvRelService;
  @Autowired
  private MinioPathUtils pathUtils;
  @Autowired
  private SimpleStorageService simpleStorageService;
  @Autowired
  private EntityNameCache entityNameCache;
  @Autowired
  private LogRabbitMQPublisher logPublisher;
  @Autowired
  private ProjectFeignClient projectFeignClient;
  @Autowired
  private ScriptFeignClient scriptFeignClient;
  @Autowired
  private AttachmentFeignClient attachmentFeignClient;
  //= Excel 导入导出相关代码 start ==================//
  @Override
  public BasicService<DataSets> getService()
  {
    return this.dataSetsService;
  }

  @Override
  public ExcelHeader[] excelHeaders()
  {
    ExcelHeader dataSetId = new ExcelHeader("数据集id", "dataSetId", String.class);
    ExcelHeader name = new ExcelHeader("数据集名称", "name", String.class);
    ExcelHeader description = new ExcelHeader("描述", "description", String.class);
    ExcelHeader proId = new ExcelHeader("系统id", "proId", String.class);
    ExcelHeader tenantId = new ExcelHeader("租户id", "tenantId", String.class);
    ExcelHeader fileAddr = new ExcelHeader("文件地址", "fileAddr", String.class);
    ExcelHeader treeId = new ExcelHeader("目录id", "treeId", String.class);
    ExcelHeader createdBy = new ExcelHeader("创建人", "createdBy", String.class);
    ExcelHeader createdTime = new ExcelHeader("创建时间", "createdTime", Date.class);
    ExcelHeader updatedBy = new ExcelHeader("更新人", "updatedBy", String.class);
    ExcelHeader updatedTime = new ExcelHeader("更新时间", "updatedTime", Date.class);
    return new ExcelHeader[]{};
  }

  /**
   * Excel导入，入库之前的处理
   * @param records 从Excel读取到的记录
   * @return 待入库的记录
   */
  @Override
  protected List<DataSets> beforeInsertBatch(List<DataSets> records)
  {
    return records;
  }

  /**
   * 写入Excel之前的处理<br>
   * 数据的特殊处理在此处加工处理
   *
   * @param record 来自数据库记录
   * @return 待写入Excel的记录
   */
  @Override
  protected DataSets beforeWriteExcel(DataSets record)
  {
    return record;
  }

  //= Excel 导入导出相关代码 end =======================//

  //= 增删改查 相关代码 start ==================//
  @Override
  @DatabaseReadOnly
  public Pagination<DataSetsDetailDto> pagingQuery(QueryByPage<DataSetsQueryDto> query)
  {
    DefaultPagination<DataSetsDetailDto> pagination = new DefaultPagination();
    //目录查询参数修改
    String treeId = query.getQuery().getTreeId();
    if (StringUtils.hasText(treeId)) {
      List<DataSetTreeDetailDto> list = dataSetTreeService.queryChildrenTreeList(treeId);
      if (!CollectionUtils.isEmpty(list)) {
        List<String> groupIds = list.stream().map(item->item.getId()).collect(Collectors.toList());
        query.getQuery().setTreeId(null);
        query.getQuery().setTreeIds(groupIds);
      }
    }
    //数据集查询租户隔离
    query.getQuery().setTenantId(NKSecurityContext.getTenantId());
    //处理分页参数
    handlePageParam(query);
    pagination.setPageSize(query.getPageSize());
    pagination.setPageNo(query.getPageNo());
    Page<DataSetsDetailDto> page = PageMethod.startPage(query.getPageNo(), query.getPageSize());  //开始分页
    List<DataSetsDetailDto> result = dataSetsService.queryDataSets(query);
    //处理返回数据
    for (DataSetsDetailDto detailDto : result) {
      //创建修改人名称
      detailDto.setCreator(entityNameCache.translateById(EntityNameCatalog.MONSTER_USER, detailDto.getCreatedBy()));
      detailDto.setModifier(entityNameCache.translateById(EntityNameCatalog.MONSTER_USER, detailDto.getUpdatedBy()));
    }
    pagination.setRecords(result);
    pagination.setRecordCount(page.getTotal());
    return pagination;
  }

  @Override
  @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  public String add(DataSetsAddDto dto)
  {
    //名称校验
    Pattern p = Pattern.compile("[\\\\/:*?\"<>|]");
    if (p.matcher(dto.getName()).find()) {
      throw new PlatformRuntimeException(DataPoolError.SET_NAME_IS_VALID);
    }
    //所选目录校验
    DataSetTree byPrimaryKey = dataSetTreeService.findByPrimaryKey(dto.getTreeId());
    if (null == byPrimaryKey || "0".equals(byPrimaryKey.getIsLeaf())) {
      throw new PlatformRuntimeException(DataPoolError.SETS_DIR_VALID);
    }

    // 校验目录下名称唯一
    boolean nameUnique = checkNameUnique(dto.getName(), dto.getTreeId(), null);
    if (!nameUnique){
      throw new PlatformRuntimeException(DataPoolError.SET_NAME_NO_UNIQUE, dto.getName());
    }

    //创建实体
    String uuid = UUIDUtil.create32UUID();
    DataSets entity = new DataSets();
    BeanUtils.copyProperties(dto, entity);
    entity.setDataSetId(uuid);
    entity.setCreatedBy(NKSecurityContext.getUserId());
    entity.setCreatedTime(new Date());
    entity.setUpdatedBy(entity.getCreatedBy());
    entity.setUpdatedTime(entity.getCreatedTime());
    entity.setTenantId(NKSecurityContext.getTenantId());
    this.dataSetsService.insert(entity);
    return uuid;
  }

  private boolean checkNameUnique(String name, String treeId, String id){
    DataSets dataSets = new DataSets();
    dataSets.setName(name);
    dataSets.setTreeId(treeId);
    List<DataSets> setsList = this.dataSetsService.query(dataSets);
    if (setsList != null && setsList.size() > 0){
      DataSets sets = setsList.get(0);
      if (!sets.getDataSetId().equals(id)){
        return Boolean.FALSE;
      }
    }
    return Boolean.TRUE;
  }

  @Override
  @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  public Integer updateByPK(DataSetsUpdateDto dto) throws IllegalAccessException
  {
    //数据集存在性校验
    DataSets byPrimaryKey = dataSetsService.findByPrimaryKey(dto.getDataSetId());
    if (null == byPrimaryKey) {
      throw new PlatformRuntimeException(DataPoolError.SETS_NO_EXISTS);
    }
    //名称校验
    Pattern p = Pattern.compile("[\\\\/:*?\"<>|]");
    if (p.matcher(dto.getName()).find()) {
      throw new PlatformRuntimeException(DataPoolError.SET_NAME_IS_VALID);
    }

    // 校验目录下名称唯一
    boolean nameUnique = checkNameUnique(dto.getName(), dto.getTreeId(), dto.getDataSetId());
    if (!nameUnique){
      throw new PlatformRuntimeException(DataPoolError.SET_NAME_NO_UNIQUE, dto.getName());
    }

    DataSets entity = new DataSets();
    BeanUtils.copyProperties(byPrimaryKey, entity);
    entity.setUpdatedBy(NKSecurityContext.getUserId());
    entity.setDescription(dto.getDescription());
    entity.setUpdatedTime(new Date());
    entity.setName(dto.getName());
    return this.dataSetsService.updateByPrimaryKey(entity);
  }

  @Override
  @DatabaseReadOnly
  public DataSetsDetailDto findByPK(String uuid)
  {
    //获取数据集
    DataSets byPrimaryKey = dataSetsService.findByPrimaryKey(uuid);
    if (null == byPrimaryKey) {
      throw new PlatformRuntimeException(DataPoolError.SETS_NO_EXISTS);
    }
    DataSetsDetailDto dto = new DataSetsDetailDto();
    BeanUtils.copyProperties(byPrimaryKey, dto);
    //获取文件数据
    if (StringUtils.hasText(dto.getFileAddr())) {
      JSONObject data = downloadFile(dto.getFileAddr());
      DataSetsSaveDto dataSetsSaveDto = null;
      if (!ObjectUtils.isEmpty(data)) {
        dataSetsSaveDto = data.toJavaObject(DataSetsSaveDto.class);
      }
      if (null != dataSetsSaveDto) {
        dto.setTableContent(dataSetsSaveDto.getTableContent());
        dto.setTableHeader(dataSetsSaveDto.getTableHeader());
      }
    }
    //封装数据集信息
    dto.setCreator(entityNameCache.translateById(EntityNameCatalog.MONSTER_USER, dto.getCreatedBy()));
    dto.setModifier(entityNameCache.translateById(EntityNameCatalog.MONSTER_USER, dto.getUpdatedBy()));
    return dto;
  }

  @Override
  @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  public Integer deleteByPK(String uuid)
  {
    //数据集存在性校验
    DataSets byPrimaryKey = dataSetsService.findByPrimaryKey(uuid);
    if (null == byPrimaryKey) {
      return 0;
    }
    //校验数据是否存在关联
    List<String> list = new ArrayList<>();
    list.add(uuid);
    List<AtuInputDataSetResultDto> dtos = scriptFeignClient.selectLinkBySetId(list);
    for (AtuInputDataSetResultDto dto : dtos) {
      if (dto.getCountNum() > 0){
        throw new PlatformRuntimeException(DataPoolError.DATA_SET_HAS_LINK);
      }
    }

    //删除对应文件
    String fileAddr = byPrimaryKey.getFileAddr();
    if (StringUtils.hasText(fileAddr)) {
      deleteFile(fileAddr);
    }
    deleteDataSetEnv(byPrimaryKey);
    //删除库数据
    int result = this.dataSetsService.deleteByPrimaryKey(byPrimaryKey);
    //删除数据集增加平台日志
    CpLogAddDto cpLogAddDto = new CpLogAddDto();
    String projectName = entityNameCache.translateById(EntityNameCatalog.MONSTER_SYSTEM.name(), byPrimaryKey.getProId());
    cpLogAddDto.setContent("【删除静态数据】系统：" + projectName + "数据集名称：" + byPrimaryKey.getName());
    cpLogAddDto.setModule("静态数据管理");
    cpLogAddDto.setType("3");
    // 发送日志到 monster
    MonsterLogServer.sendLogToMonster(cpLogAddDto);
    logPublisher.deployLogContent(cpLogAddDto);
    return result;
  }

  private void deleteDataSetEnv(DataSets byPrimaryKey) {
    DataSetEnvRel record = new DataSetEnvRel();
    record.setDataSetId(byPrimaryKey.getDataSetId());
    List<DataSetEnvRel> dataSetEnvRels = dataSetEnvRelService.query(record);
    dataSetEnvRels.forEach(dataSetEnvRel -> {
      if (StringUtils.hasText(dataSetEnvRel.getFileAddr())) {
        deleteFile(dataSetEnvRel.getFileAddr());
      }
    });
    //删除环境数据
    List<Object> deleteIds = dataSetEnvRels.stream().map(DataSetEnvRel::getId).collect(Collectors.toList());
    if (!CollectionUtils.isEmpty(deleteIds)) {
      dataSetEnvRelService.deleteByPrimaryKeys(deleteIds);
    }
  }

  @Override
  @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  public Integer deleteBatch(DataSetsDeleteDto dto)
  {
    List<String> setIds = dto.getSetIds();
    if (CollectionUtils.isEmpty(setIds)) {
      return 0;
    }

    List<AtuInputDataSetResultDto> dtos = scriptFeignClient.selectLinkBySetId(dto.getSetIds());
    for (AtuInputDataSetResultDto resultDto : dtos) {
      if (resultDto.getCountNum() > 0){
        throw new PlatformRuntimeException(DataPoolError.DATA_SET_HAS_LINK);
      }
    }
    //删除文件 记录删除的系统和数据集
    List<DataSets> dataSets = dataSetsService.queryByIds(setIds);
    List<String> proIds = new ArrayList<>();
    List<String> setNames = new ArrayList<>();
    for (DataSets dataSet : dataSets) {
      if (null != dataSet) {
        if (StringUtils.hasText(dataSet.getProId())) {
          proIds.add(dataSet.getProId());
        }
        if (StringUtils.hasText(dataSet.getName())) {
          setNames.add(dataSet.getName());
        }
        if (StringUtils.hasText(dataSet.getFileAddr())) {
          deleteFile(dataSet.getFileAddr());
        }
      }
    }
    //未获取到系统或数据集名称
    if (CollectionUtils.isEmpty(proIds) || CollectionUtils.isEmpty(setNames)) {
      return 0;
    }
    for (DataSets dataSet : dataSets) {
      deleteDataSetEnv(dataSet);
    }
    //删除数据
    Integer result = dataSetsService.deleteByIds(setIds);
    //批量删除数据集增加平台日志（均为同系统
    String projectName = entityNameCache.translateById(EntityNameCatalog.MONSTER_SYSTEM.name(), proIds.get(0));
    CpLogAddDto cpLogAddDto = new CpLogAddDto();
    cpLogAddDto.setContent("【批量删除静态数据集】：系统" + projectName + "，共" + result + "条");
    cpLogAddDto.setModule("静态数据管理");
    cpLogAddDto.setType("3");
    cpLogAddDto.setContentDetails(setNames);
    MonsterLogServer.sendLogToMonster(cpLogAddDto);
    logPublisher.deployLogContent(cpLogAddDto);
    return result;
  }

  @Override
  @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  public Boolean save(DataSetsSaveDto dto) {
    //获取数据集数据
    String dataSetId = dto.getDataSetId();
    DataSets byPrimaryKey = dataSetsService.findByPrimaryKey(dataSetId);
    if (null == byPrimaryKey) {
      throw new PlatformRuntimeException(DataPoolError.SETS_NO_EXISTS);
    }
    //校验表头是否正确
    List<DataHeaderDto> tableHeader = dto.getTableHeader();
    List<String> colNameList = checkColumnList(tableHeader);
    //校验数据是否正确
    Map<String, List<DataContentDto>> tableContent = dto.getTableContent();
    if (!colNameList.containsAll(tableContent.keySet())) {
      throw new PlatformRuntimeException(DataPoolError.HEADER_CONTENT_NO_MATCH);
    }
    //存储文件
    String path = null;
    try {
      String filePath = uploadFile(dto, byPrimaryKey.getDataSetId(), FileBusinessTypeEnum.STATIC_DATA_SET);
      if (StringUtils.hasText(filePath)) {
        path = filePath;
      }
    }catch (Exception e) {
      throw new PlatformRuntimeException(DataPoolError.FILE_UPLOAD_ERROR);
    }
    //更新数据集数据
    DataSets dataSets = new DataSets();
    BeanUtils.copyProperties(byPrimaryKey,dataSets);
    dataSets.setFileAddr(path);
    dataSets.setUpdatedBy(NKSecurityContext.getUserId());
    dataSets.setUpdatedTime(new Date());
    dataSetsService.updateByPrimaryKey(dataSets);
    //删除原文件
    String oldPath = byPrimaryKey.getFileAddr();
    if (StringUtils.hasText(oldPath)) {
      deleteFile(oldPath);
    }
    return true;
  }

  @Override
  public Boolean checkTableHeader(ColumnCheckDto dto) {
    String dataSetId = dto.getDataSetId();
    DataSets byPrimaryKey = dataSetsService.findByPrimaryKey(dataSetId);
    if (null == byPrimaryKey) {
      throw new PlatformRuntimeException(DataPoolError.SETS_NO_EXISTS);
    }
    if (null == dto.getColumnInfo()) {
      throw new PlatformRuntimeException(DataPoolError.COLUMN_IS_NULL);
    }
    String fileAddr = byPrimaryKey.getFileAddr();
    //新增列
    if (StringUtils.hasText(fileAddr)) {
      JSONObject dataInfo = downloadFile(fileAddr);
      if (!ObjectUtils.isEmpty(dataInfo)) {
        DataSetsSaveDto data = dataInfo.toJavaObject(DataSetsSaveDto.class);
        List<DataHeaderDto> tableHeader = data.getTableHeader();
        List<String> columnList = tableHeader.stream().map(item->item.getName()).collect(Collectors.toList());
        if (columnList.contains(dto.getColumnInfo().getName())) {
          throw new PlatformRuntimeException(DataPoolError.COLUMN_IS_EXSITS);
        }
      }
    }
    return true;
  }

  @Override
  public void exportDataSet(HttpServletResponse response, String dataSetId, String fileName) {
    DataSets dataSet = dataSetsService.findByPrimaryKey(dataSetId);
    if (null == dataSet) {
      throw new PlatformRuntimeException(DataPoolError.SETS_NO_EXISTS);
    }
    dataSetDownloadExecl(response, dataSet.getName());
    ServletOutputStream outputStream = null;
    try {
      Workbook workbook = exportDataTable(dataSet);
      outputStream = response.getOutputStream();
      workbook.write(outputStream);
      outputStream.flush();
    } catch (IOException e) {
      logger.error("导出" + dataSet.getName() + "数据集文件失败：", e);
    } finally {
      if (null != outputStream) {
        try {
          outputStream.close();
        } catch (IOException e) {
          logger.error("",e);
        }
      }
    }
  }

  @Override
  public void downloadTemplate(HttpServletResponse response, String fileName, DataSetsSaveDto saveDto) {
    DataSets dataSet = dataSetsService.findByPrimaryKey(saveDto.getDataSetId());
    if (null == dataSet) {
      throw new PlatformRuntimeException(DataPoolError.SETS_NO_EXISTS);
    }
    dataSetDownloadExecl(response, dataSet.getName() + "模板");
    ServletOutputStream outputStream = null;
    saveDto.setTableContent(null);
    try {
      Workbook workbook = ExcelUtils.exportToExcel(saveDto, dataSet.getName(), true);
      outputStream = response.getOutputStream();
      workbook.write(outputStream);
      outputStream.flush();
    } catch (IOException e) {
      logger.error("导出" + dataSet.getName() + "模板文件失败：", e);
    } finally {
      if (null != outputStream) {
        try {
          outputStream.close();
        } catch (IOException e) {
          logger.error("",e);
        }
      }
    }
  }

  @Override
  @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
  public String createDataSet(DataSetsAddDto inputDto) {
    String setId = add(inputDto);
    List<String> headers = inputDto.getHeaders();
    List<Map<String, Object>> tableData = inputDto.getTableData();
    //保存表数据
    if (!CollectionUtils.isEmpty(headers)) {
      DataSetsSaveDto saveDto = new DataSetsSaveDto();
      List<DataHeaderDto> headerList = new ArrayList<>();
      //记录表头信息
      for (String colName : headers) {
        if(!StringUtils.hasText(colName)) {
          throw new PlatformRuntimeException(DataPoolError.COLUMN_IS_NULL);
        }
        DataHeaderDto dataHeaderDto = new DataHeaderDto();
        dataHeaderDto.setName(colName);
        dataHeaderDto.setType("string");
        dataHeaderDto.setIsRepeat("1");
        headerList.add(dataHeaderDto);
      }
      saveDto.setTableHeader(headerList);

      // 同步至其他环境只需要表头即可
      DataSetsSaveDto syncSaveDto = new DataSetsSaveDto();
      syncSaveDto.setTableHeader(headerList);

      //记录表数据
      Map<String,List<DataContentDto>> contentList = new HashMap<>();
      for(int col = 0; col < headers.size(); col++) {
        String name = headers.get(col);
        List<DataContentDto> colDatas = new ArrayList<>();
        //逐行获取该列值
        for (int row = 0; row < tableData.size(); row++) {
          DataContentDto contentDto = new DataContentDto();
          Map<String, Object> rowData = tableData.get(row);
          String val = "";
          //有值替换 无值存空串
          if (rowData.containsKey(name)) {
            Object value = rowData.get(name);
            if (value != null && StringUtils.hasText(value.toString()) && !"null".equals(value.toString())) {
              val = value.toString();
            }
          }
          contentDto.setValue(val);
          contentDto.setTime("0");
          colDatas.add(contentDto);
        }
        contentList.put(name,colDatas);
      }
      saveDto.setTableContent(contentList);
      //将数据上传文件服务器
      String path = uploadFile(saveDto, setId, FileBusinessTypeEnum.STATIC_DATA_SET);
      if (StringUtils.hasText(path)) {
        DataSets dataSets = new DataSets();
        dataSets.setDataSetId(setId);
        dataSets.setFileAddr(path);
        dataSetsService.updateByPrimaryKey(dataSets);
        //更新到每个环境下
        List<String> envIds = projectFeignClient.selectEnvIds(inputDto.getProId());
        int seq = 1;
        for (String envId : envIds) {
          DataSetEnvRel dataSetEnvRel = new DataSetEnvRel();
          dataSetEnvRel.setId(UUIDUtil.create32UUID());//主键
          dataSetEnvRel.setDataSetId(setId);//数据集id
          dataSetEnvRel.setEnvId(envId);//环境id
          // 环境相同保存标题和数据，其他环境只保存表头
          if (Objects.equals(inputDto.getEnvId(), envId)){
            String envPath = uploadFile(saveDto, dataSetEnvRel.getId(), FileBusinessTypeEnum.STATIC_DATA_SET_ENV);
            dataSetEnvRel.setFileAddr(envPath);//文件路径
          }else {
            String syncFilePath = uploadFile(syncSaveDto, dataSetEnvRel.getId(), FileBusinessTypeEnum.STATIC_DATA_SET_ENV);
            dataSetEnvRel.setFileAddr(syncFilePath);//文件路径
          }
          dataSetEnvRel.setSeq(seq);//排序
          dataSetEnvRel.setCreatedBy(NKSecurityContext.getUserId());
          dataSetEnvRel.setUpdatedBy(NKSecurityContext.getUserId());
          dataSetEnvRel.setCreatedTime(new Date());
          dataSetEnvRel.setUpdatedTime(new Date());
          dataSetEnvRel.setTenantId(NKSecurityContext.getTenantId());
          dataSetEnvRelService.insert(dataSetEnvRel);
        }
      }else {
        throw new PlatformRuntimeException(DataPoolError.FILE_ID_ERROR);
      }
    }
    return setId;
  }

  private void dataSetDownloadExecl(HttpServletResponse response, String fileName) {
    response.reset();
    response.setStatus(HttpStatus.OK.value());
    response.setCharacterEncoding("UTF-8");
    try {
      fileName = URLEncoder.encode(fileName,"UTF-8");
    } catch (UnsupportedEncodingException e) {
      logger.error("文件名转换编码异常", e);
    }
    response.setHeader("Content-Type", "application/octet-stream");
    response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
  }

  private Workbook exportDataTable(DataSets dataSet) {
    String fileAddr = dataSet.getFileAddr();
    if (StringUtils.hasText(fileAddr)) {
      JSONObject jsonObject = downloadFile(fileAddr);
      if (!ObjectUtils.isEmpty(jsonObject)) {
        DataSetsSaveDto dataInfo = jsonObject.toJavaObject(DataSetsSaveDto.class);
        return ExcelUtils.exportToExcel(dataInfo, dataSet.getName(), true);
      }else {
        return ExcelUtils.exportToExcel(null, dataSet.getName(), true);
      }
    }else {
      return ExcelUtils.exportToExcel(null, dataSet.getName(), true);
    }
  }

  /**
   * 校验表头是否正确
   * @param columnList
   * @return
   */
  private List<String> checkColumnList(List<DataHeaderDto> columnList) {
    List<String> names = new ArrayList<>();
    //校验是否存在同名列
    if (!CollectionUtils.isEmpty(columnList)) {
      names = new ArrayList<>();
      for (DataHeaderDto dataHeaderDto : columnList) {
        if (null == dataHeaderDto) {
          throw new PlatformRuntimeException(DataPoolError.COLUMN_IS_NULL);
        }
        //列名称校验
        String headName = dataHeaderDto.getName();
        if (!StringUtils.hasText(headName)) {
          throw new PlatformRuntimeException(DataPoolError.COLUMN_NAME_IS_NULL);
        }
        if (headName.length() > 30) {
          throw new PlatformRuntimeException(DataPoolError.COLUMN_NAME_IS_TOO_LONG);
        }
        if (names.contains(headName)) {
          throw new PlatformRuntimeException(DataPoolError.COLUMN_IS_EXSITS);
        }
        //列类型校验
        String headType = dataHeaderDto.getType();
        if (!StringUtils.hasText(headType)) {
          throw new PlatformRuntimeException(DataPoolError.COLUMN_TYPE_IS_NULL);
        }
        String code = DataHeaderType.getCode(headType);
        if (!StringUtils.hasText(code)) {
          throw new PlatformRuntimeException(DataPoolError.COLUMN_TYPE_IS_WRONG);
        }
        names.add(headName);
      }
    }
    return names;
  }

  /**
   * 处理分页查询参数
   *
   * @param query
   */
  private void handlePageParam(QueryByPage<DataSetsQueryDto> query) {
    if (query.getPageNo() <= 0) {
      query.setPageNo(1);
    }
    if (query.getPageSize() <= 0 || query.getPageSize() > 500) {
      query.setPageSize(500);
    }
    OrderBy sort = query.toSqlOrderBy();
    if (sort != null && sort.isNotEmpty() && StringUtils.hasText(sort.toString())) {
      PageMethod.orderBy(sort.toString());
    }
  }

  /**
   * 根据url下载文件
   * @param url
   * @return
   */
  private JSONObject downloadFile(String url) {
    String[] resultPath = MinioPathUtils.idToPath(url);
    InputStream inputStream = null;
    JSONObject scriptData = null;
    try {
      inputStream = simpleStorageService.downloadAsStream(resultPath[0], "/" + resultPath[1]);
      scriptData = MinioPathUtils.getFileContent(inputStream, JSONObject.class);
      return scriptData;
    } catch (FileDownloadException e) {
      logger.error("读取原文件失败，失败原因：", e);
      throw new PlatformRuntimeException(DataPoolError.FILE_DOWNLOAD_ERROR);
    } finally {
      if (null != inputStream) {
        try {
          inputStream.close();
        } catch (IOException e) {
          logger.error("",e);
        }
      }
    }
  }

  /**
   * 根据url删除服务器端文件
   * @param url
   */
  private void deleteFile(String url) {
    String[] pathData = MinioPathUtils.idToPath(url);
    try {
      simpleStorageService.delete(pathData[0], "/" + pathData[1]);
    } catch (Exception e) {
      throw new PlatformRuntimeException(DataPoolError.FILE_DEL_ERROR);
    }
  }

  /**
   * 上传文件
   * @param scriptJsonStr
   * @return
   */
  private String uploadFile(Object scriptJsonStr, String objId, FileBusinessTypeEnum businessCode) {
    File file = MinioPathUtils.objectToJsonFile(scriptJsonStr);
    try {
      NKFile nkFile = simpleStorageService.upload(NKSecurityContext.getTenantId(), file, objId, businessCode);
      return MinioPathUtils.pathToId(NKSecurityContext.getTenantId(), nkFile.getId());
    } catch (FileUploadException e) {
      logger.error("上传文件出错", e);
      throw new PlatformRuntimeException(DataPoolError.FILE_UPLOAD_ERROR);
    } finally {
      boolean delete = file.delete();
      if (!delete) {
        logger.error("删除文件失败");
      }
    }
  }
}
