package com.bcxin.backend.domain.utils.ftp;

import com.bcxin.backend.domain.configs.FileModeConfig;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StopWatch;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <b> 批量上传 </b>
 * @author ZXF
 * @create 2023/07/07 0007 13:43
 * @version
 * @注意事项 </b>
 */
public class FtpUtil {
    private static final Logger logger = LoggerFactory.getLogger(FtpUtil.class);

    /**
     * 上传文件
     *
     * @param ftpPath
     * @param listFiles
     * @return
     */

    public static synchronized List<UploadResult> upload(String ftpPath, File[] listFiles) {
        //构建线程池
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(FileModeConfig.threadPoolSize);
        List<Future> results = new ArrayList<>();
        //创建n个ftp链接
        FtpFactory factory = new FtpFactory();
        List<UploadResult> listResults = new ArrayList<>();
        Exception lastException = null;
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        try {
            long a = System.currentTimeMillis();
            for (File file : listFiles) {
                if (file.isDirectory()) {
                    continue;
                }
                //根据文件最后修改时间，如果小于5分钟的不进行上传（可能文件还没写入流）
                long createTime = file.lastModified();
                if (((a - createTime) / 60 / 1000) < 5) {
                    continue;
                }

                FtpConnection ftp = factory.getFtp();//获取ftp con
                UploadTask upload = new UploadTask(factory, ftp, file, ftpPath, file.getName());

                Future submit = newFixedThreadPool.submit(upload);
                results.add(submit);
            }

            listResults = results.parallelStream().map(result -> {
                try {
                    return (UploadResult) result.get(30, TimeUnit.MINUTES);
                } catch (Exception ex) {
                    logger.error("获取上传FTP结果异常", ex);

                    return null;
                }
            }).collect(Collectors.toList());
        } catch (Exception ex) {
            lastException = ex;

            throw ex;
        } finally {
            factory.close();
            newFixedThreadPool.shutdown();

            stopWatch.stop();
            logger.error("完成({})FTP的执行(预期数={}, 实际响应数={}),耗时:{}秒",
                    (lastException == null ? "成功" : "异常"),
                    results.size(),
                    listResults.size(),
                    stopWatch.getTotalTimeSeconds(), lastException);
        }

        return listResults;
    }


    /**
     * <b> 将base64字符流写入指定文件 </b>
     * @author ZXF
     * @create 2024/11/27 0027 8:46
     * @version
     * @注意事项 </b>
     */
    public static boolean uploadBase64(String ftpPath, String ftpFileName, String base64Content) {
        boolean result = false;
        try {
            //创建n个ftp链接
            FtpFactory factory = new FtpFactory();
            FtpConnection ftp = factory.getFtp();//获取ftp con
            result = ftp.uploadBase64(ftpPath, ftpFileName, base64Content);

        } catch (IOException e) {
            logger.error("=======>上传base64文件(ftpPath={}, fileName={})失败ftp异常", ftpPath, ftpFileName, e);
        }
        return result;
    }

    /**
     * 下载文件
     * @param path:ftp文件目录
     * @param filename:ftp文件目录下某文件名
     * @param dstFile:保存的文件或文件夹，若指定文件名称就使用指定的名称和目录，若是文件夹则文件名称采用ftp上要下载的文件的名称
     */
    public static boolean downloadFile(String path,String filename, File dstFile) {
        boolean result = false;
        try {
            //创建n个ftp链接
            FtpFactory factory = new FtpFactory();
            FtpConnection ftp = factory.getFtp();//获取ftp con
            result = ftp.download(path, filename, dstFile);

        } catch (IOException e) {
            logger.error("=======>downloadFile文件(path={}, filename={})失败ftp异常", path, filename, e);
        }
        return result;
    }

    public static String downloadAsBase64(String path,String filename) {
        String result = "";
        try {
            //创建n个ftp链接
            FtpFactory factory = new FtpFactory();
            FtpConnection ftp = factory.getFtp();//获取ftp con
            result = ftp.downloadAsBase64(path, filename);

        } catch (IOException e) {
            logger.error("=======>downloadAsBase64(path={}, filename={})失败ftp异常", path, filename, e);
        }
        return result;
    }

    /**
     * <b> 获取ftp目录下所有最近5分钟内生成的文件的文件名，返回文件名列表 </b>
     * @author ZXF
     * @create 2024/11/27 0027 8:44
     * @version
     * @注意事项 </b>
     */
    public static List<String> filenames(String path,String keywork) {
        try {
            //创建n个ftp链接
            FtpFactory factory = new FtpFactory();
            FtpConnection ftp = factory.getFtp();//获取ftp con
            return ftp.fileNames(path,keywork);
        } catch (IOException e) {
            logger.error("=======>filenames(path={}, filename={})失败ftp异常", path, keywork, e);
        }
        return new ArrayList<>();
    }


    public static boolean delFilename(String path,String filename) {
        try {
            //创建n个ftp链接
            FtpFactory factory = new FtpFactory();
            FtpConnection ftp = factory.getFtp();//获取ftp con
            return ftp.delectFile(path,filename);
        } catch (IOException e) {
            logger.error("=======>delFilename(path={}, filename={})失败ftp异常", path, filename, e);
        }
        return false;
    }

    /**
     * <b> 获取ftp指定文件的文件内容 </b>
     * @author ZXF
     * @create 2024/11/27 0027 8:45
     * @version
     * @注意事项 </b>
     */
    public static String getFileContent(String path, String ftpFileName) {
        try {
            //创建n个ftp链接
            FtpFactory factory = new FtpFactory();
            FtpConnection ftp = factory.getFtp();//获取ftp con
            return ftp.getFileContent(path, ftpFileName);
        } catch (IOException e) {
            logger.error("=======>getFileContent(path={}, filename={})失败ftp异常", path, ftpFileName, e);
        }

        return "";
    }
}