package com.jiayue.ipfcst.fileupload.job;

import com.jiayue.ipfcst.common.data.entity.UploadFileChannel;
import com.jiayue.ipfcst.common.data.repository.UploadFileChannelRepository;
import com.jiayue.ipfcst.common.data.repository.UploadFileLogRepository;
import com.jiayue.ipfcst.fileupload.util.FileUtil;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.io.*;

import java.text.SimpleDateFormat;

import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 前一日上报成功文件压缩任务
 *
 * @Author tl
 * @CreateTime 2021/8/30 9:16
 */
@Slf4j
@Service
@EnableScheduling
public class ReportFileCompressionJob {

  private static final int  BUFFER_SIZE = 2 * 1024;

  private static boolean flag;


  @Autowired
  private UploadFileChannelRepository uploadFileChannelRepository;



  @Scheduled(cron = "0 55 1 1/1 * ?")
  public void compression() {
    log.info("定时压缩前一日已上报文件定时任务开始 ---------------------》");
    flag = true;

    long l = System.currentTimeMillis() - 86400000;


    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
    String yesterday = sdf.format(l);
    String backupsPath = FileUtil.getFileUploadPath() + File.separator + "backups" +File.separator + yesterday;

    String errorPath = FileUtil.getFileUploadPath() + File.separator + "error" +File.separator + yesterday;
    File destDirB = new File(backupsPath);
    File destDirE = new File(errorPath);
    if (destDirB.exists()) zip(backupsPath,destDirB);
    if (destDirE.exists()) zip(errorPath,destDirE);
    log.info("定时压缩前一日已上报文件定时任务结束 《---------------------");
  }


  public void zip(String path,File file){
    FileOutputStream fos = null;
    try {
      fos = new FileOutputStream(new File(path+".zip"));
      toZip(path,fos,true);
      if (flag){
        //压缩成功后删除目录
        delFile(file);
        log.info("压缩成功，将【"+path+"]目录删除");
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }

  }

  //递归删除法
  static boolean delFile(File file) {
    if (file.isDirectory()) {
      File[] files = file.listFiles();
      for (File f : files) {
        delFile(f);
      }
    }
    return file.delete();
  }

  public static void toZip (String srcDir, OutputStream out,boolean KeepDirStructure) throws RuntimeException {

    long start = System.currentTimeMillis();
    ZipOutputStream zos = null;
    try {
      zos = new ZipOutputStream(out);
      File sourceFile = new File(srcDir);
      compress(sourceFile, zos, sourceFile.getName(), KeepDirStructure);
      long end = System.currentTimeMillis();
      log.info("前一日已上报文件压缩完成，耗时：" + (end - start) + " ms");
    } catch (Exception e) {
      flag = false;
      throw new RuntimeException("已上报文件压缩错误！！！", e);
    } finally {
      if (zos != null) {
        try {
          zos.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }

  }

  /**
   * 递归压缩方法
   * @param sourceFile 源文件
   * @param zos        zip输出流
   * @param name       压缩后的名称
   * @param KeepDirStructure  是否保留原来的目录结构,true:保留目录结构;
   *                          false:所有文件跑到压缩包根目录下(注意：不保留目录结构可能会出现同名文件,会压缩失败)
   * @throws Exception
   */
  private static void compress(File sourceFile, ZipOutputStream zos, String name,
                               boolean KeepDirStructure) throws Exception{
    byte[] buf = new byte[BUFFER_SIZE];
    if(sourceFile.isFile()){
      // 向zip输出流中添加一个zip实体，构造器中name为zip实体的文件的名字
      zos.putNextEntry(new ZipEntry(name));
      // copy文件到zip输出流中
      int len;
      FileInputStream in = null;
      try{
        in = new FileInputStream(sourceFile);
        while ((len = in.read(buf)) != -1){
          zos.write(buf, 0, len);
        }
        // Complete the entry
        zos.closeEntry();
      }
      catch (Exception e){
        e.printStackTrace();
      }
      finally {
        if (in!=null){
          in.close();
        }
      }

    } else {
      File[] listFiles = sourceFile.listFiles();
      if(listFiles == null || listFiles.length == 0){
        // 需要保留原来的文件结构时,需要对空文件夹进行处理
        if(KeepDirStructure){
          // 空文件夹的处理
          zos.putNextEntry(new ZipEntry(name + "/"));
          // 没有文件，不需要文件的copy
          zos.closeEntry();
        }

      }else {
        for (File file : listFiles) {
          // 判断是否需要保留原来的文件结构
          if (KeepDirStructure) {
            // 注意：file.getName()前面需要带上父文件夹的名字加一斜杠,
            // 不然最后压缩包中就不能保留原来的文件结构,即：所有文件都跑到压缩包根目录下了
            compress(file, zos, name + "/" + file.getName(),KeepDirStructure);
          } else {
            compress(file, zos, file.getName(),KeepDirStructure);
          }
        }
      }
    }
  }
}
