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

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.enums.FileBusinessTypeEnum;
import net.northking.cctp.common.exception.PlatformRuntimeException;
import net.northking.cctp.common.http.QueryByPage;
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.db.entity.DataResourcePackage;
import net.northking.cctp.dataPool.db.service.DataResourcePackageService;
import net.northking.cctp.dataPool.dto.dataRule.DataResourcePackageDetailDto;
import net.northking.cctp.dataPool.dto.dataRule.DataResourcePackageQueryDto;
import net.northking.cctp.dataPool.dto.dataRule.DataResourcePackageUpdateDto;
import net.northking.cctp.dataPool.enums.DataPoolError;
import net.northking.cctp.dataPool.utils.MinioPathUtils;
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.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.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.Date;
import java.util.List;

/**
 * 资源包服务实现类
 *
 * @author maven-cctp-plugin
 * @since 1.0
 */

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

  @Autowired
  private DataResourcePackageService dataResourcePackageService;
  @Autowired
  private MinioPathUtils pathUtils;
  @Autowired
  private SimpleStorageService simpleStorageService;
  @Autowired
  private EntityNameCache entityNameCache;

  @Override
  public BasicService<DataResourcePackage> getService()
  {
    return this.dataResourcePackageService;
  }

  @Override
  public ExcelHeader[] excelHeaders()
  {
    ExcelHeader id = new ExcelHeader("id", "id", String.class);
    ExcelHeader name = new ExcelHeader("资源包名称", "name", String.class);
    ExcelHeader memo = new ExcelHeader("资源包描述", "memo", String.class);
    ExcelHeader packageAddr = new ExcelHeader("资源包存放地址", "packageAddr", String.class);
    ExcelHeader proId = new ExcelHeader("系统id", "proId", String.class);
    ExcelHeader tenantId = new ExcelHeader("租户id", "tenantId", String.class);
    ExcelHeader createdBy = new ExcelHeader("创建人", "createdBy", String.class);
    ExcelHeader updatedBy = new ExcelHeader("更新人", "updatedBy", String.class);
    ExcelHeader createdTime = new ExcelHeader("创建时间", "createdTime", Date.class);
    ExcelHeader updatedTime = new ExcelHeader("更新时间", "updatedTime", Date.class);
    return new ExcelHeader[]{};
  }

  /**
   * Excel导入，入库之前的处理
   * @param records 从Excel读取到的记录
   * @return 待入库的记录
   */
  @Override
  protected List<DataResourcePackage> beforeInsertBatch(List<DataResourcePackage> records)
  {
    for (DataResourcePackage record : records)
    {
      record.setId(UUIDUtil.create32UUID());
    }
    return records;
  }

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

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

  //= 增删改查 相关代码 start ==================//
  @Override
  @DatabaseReadOnly
  public Pagination<DataResourcePackageDetailDto> pagingQuery(QueryByPage<DataResourcePackageQueryDto> queryByPage)
  {
    DefaultPagination<DataResourcePackageDetailDto> pagination = new DefaultPagination<>();
    handlePageParam(queryByPage);  //处理分页、排序参数
    //租户隔离
    queryByPage.getQuery().setTenantId(NKSecurityContext.getTenantId());
    pagination.setPageSize(queryByPage.getPageSize());
    pagination.setPageNo(queryByPage.getPageNo());

    Page<DataResourcePackageDetailDto> page = PageMethod.startPage(queryByPage.getPageNo(), queryByPage.getPageSize());
    List<DataResourcePackageDetailDto> result = dataResourcePackageService.getDataResourcePackages(queryByPage);
    if (!CollectionUtils.isEmpty(result)) {
      for (DataResourcePackageDetailDto data : result) {
        data.setCreator(entityNameCache.translateById(EntityNameCatalog.MONSTER_USER,data.getCreatedBy()));
      }
    }
    pagination.setRecords(result);
    pagination.setRecordCount(page.getTotal());
    return pagination;
  }

  @Override
  @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
  public Integer updateByPK(DataResourcePackageUpdateDto dto) throws IllegalAccessException
  {
    DataResourcePackage oldData = dataResourcePackageService.findByPrimaryKey(dto.getId());
    if (oldData == null) {
      throw new PlatformRuntimeException(DataPoolError.DATA_RESOURCE_PACKAGE_IS_NULL);
    }
    DataResourcePackage entity = new DataResourcePackage();
    BeanUtils.copyProperties(oldData, entity);
    entity.setUpdatedTime(new Date());
    entity.setUpdatedBy(NKSecurityContext.getUserId());
    entity.setMemo(dto.getMemo());
    return this.dataResourcePackageService.updateByPrimaryKey(entity);
  }



  @Override
  @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
  public Integer deleteByPK(String uuid)
  {
    DataResourcePackage oldData = dataResourcePackageService.findByPrimaryKey(uuid);
    if (oldData == null) {
      throw new PlatformRuntimeException(DataPoolError.DATA_RESOURCE_PACKAGE_IS_NULL);
    }
    String oldPath = oldData.getPackageAddr();
    //删除数据
    DataResourcePackage entity = new DataResourcePackage();
    BeanUtils.copyProperties(oldData, entity);
    int res = this.dataResourcePackageService.deleteByPrimaryKey(entity);
    //删除文件
    deleteFile(oldPath);
    return res;
  }

  @Override
  @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
  public DataResourcePackage uploadResource(MultipartFile file,String proId,String memo) {
    logger.info("上传资源包，资源包名称：{}，资源包大小：{}B", file.getOriginalFilename(), file.getSize());
    //1.获取前端传过来的文件 判断是否为空
    if (file.isEmpty()) {
      //判断文件的大小是否为空 如果为空 给出提示信息提示
      throw new PlatformRuntimeException(DataPoolError.IMPORT_FILE_IS_NULL);
    }
    //读取文件名
    String fileName = file.getOriginalFilename();
    //获取文件名的后缀 并判断
    String suffix = fileName.substring(fileName.lastIndexOf("."));
    if (!suffix.endsWith(".jar")) {
      throw new PlatformRuntimeException(DataPoolError.IMPORT_FILE_FORMART_IS_ERROR);
    }
    try {
      DataResourcePackage query = new DataResourcePackage();
      query.setName(fileName);
      List<DataResourcePackage> list = this.dataResourcePackageService.query(query);
      boolean add = true;
      DataResourcePackage dataResourcePackage = null;
      String oldPath = "";
      if (!CollectionUtils.isEmpty(list)) {
        //存在同名资源包则做覆盖
        dataResourcePackage = list.get(0);
        oldPath = dataResourcePackage.getPackageAddr();
        add = false;
      } else {
        DataResourcePackage resource = new DataResourcePackage();
        resource.setId(UUIDUtil.create32UUID());
        resource.setName(fileName);
        dataResourcePackage = resource;
      }
      try {
        NKFile nkFile = simpleStorageService.upload(NKSecurityContext.getTenantId(), file, dataResourcePackage.getId(), FileBusinessTypeEnum.DATA_RUL_RESOURCE_PACKAGE);
        String filePath = nkFile.getId();
        String fileId = MinioPathUtils.pathToId(NKSecurityContext.getTenantId(),filePath);
        dataResourcePackage.setPackageAddr(fileId);
      } catch (Exception e) {
        throw new PlatformRuntimeException(DataPoolError.FILE_UPLOAD_ERROR);
      }

      dataResourcePackage.setProId(proId);
      dataResourcePackage.setMemo(memo);
      dataResourcePackage.setCreatedBy(NKSecurityContext.getUserId());
      dataResourcePackage.setTenantId(NKSecurityContext.getTenantId());
      dataResourcePackage.setUpdatedBy(dataResourcePackage.getCreatedBy());
      dataResourcePackage.setCreatedTime(new Date());
      dataResourcePackage.setUpdatedTime(dataResourcePackage.getCreatedTime());
      if (add) {
        this.dataResourcePackageService.insert(dataResourcePackage);
      } else {
        this.dataResourcePackageService.updateByPrimaryKey(dataResourcePackage);
        //删除原文件
        if (StringUtils.hasText(oldPath)) {
          deleteFile(oldPath);
        }
      }
      logger.info("资源包上传完成，路径：{}",dataResourcePackage.getPackageAddr());
      return dataResourcePackage;
    } catch (Exception e) {
      logger.error("上传资源包失败：",e);
      throw new PlatformRuntimeException(DataPoolError.DATA_RESOURCE_PACKAGE_UPLOAD_FAIL);
    }
  }


  /**
   * 处理分页查询参数
   *
   * @param query
   */
  private void handlePageParam(QueryByPage<DataResourcePackageQueryDto> 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
   */
  private void deleteFile(String url) {
    String[] pathData = pathUtils.idToPath(url);
    try {
      simpleStorageService.delete(pathData[0], "/" + pathData[1]);
    } catch (Exception e) {
      throw new PlatformRuntimeException(DataPoolError.FILE_DEL_ERROR);
    }
  }
}
