package com.bcxin.signature.util.ftp;

import com.bcxin.signature.config.FileModeConfig;
import com.bcxin.signature.util.ThreadUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * <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 listFileName
     * @return
     */

    public static synchronized List<DownloadResult> download(String ftpPath, String[] listFileName) {
        String cont = "";
        //构建线程池
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(FileModeConfig.threadPoolSize);
        List<Future> results = new ArrayList<>();
        //创建n个ftp链接
//        FtpFactory factory = new FtpFactory();
        for (String fileName : listFileName) {
//            FtpConnection ftp = factory.getFtp();//获取ftp con
            DownloadTask upload = new DownloadTask(null,null, ftpPath, fileName);
            Future submit = newFixedThreadPool.submit(upload);
            results.add(submit);
        }

        List<DownloadResult> listResults = new ArrayList<>();
        for (Future result : results) {
            try {
                //获取线程结果
                DownloadResult uploadResult = (DownloadResult)result.get(15, TimeUnit.SECONDS);
                System.err.println("=======>    FTP download DownloadResult："+StringUtils.isNotEmpty(uploadResult.getContent())+"   <=======");
                listResults.add(uploadResult);
            } catch (Exception e) {
                if(StringUtils.isEmpty(cont)&&e.getMessage().contains("SocketException: Broken pipe")){
                    cont = e.getMessage();
                }
                System.err.println("=======>线程池下载ftp异常："+e.getMessage()+"<=======");
//                e.printStackTrace();
            }
        }
//        factory.close();
        newFixedThreadPool.shutdown();
        if(StringUtils.isNotEmpty(cont)){
            listResults = null;
        }
        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();//连接FTP
            FtpConnection ftp = factory.getFtp();//获取ftp con
            result = ftp.uploadBase64(ftpPath, ftpFileName, base64Content);

        } catch (IOException e) {
            System.err.println("=======>上传base64文件失败ftp异常："+e.getMessage()+"<=======");
        }
        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();//连接FTP
            FtpConnection ftp = factory.getFtp();//获取ftp con
            result = ftp.download(path, filename, dstFile);

        } catch (IOException e) {
            System.err.println("=======>下载文件失败ftp异常："+e.getMessage()+"<=======");
        }
        return result;
    }

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

        } catch (IOException e) {
            System.err.println("=======>下载文件输出base64失败ftp异常："+e.getMessage()+"<=======");
        }
        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();//连接FTP
            FtpConnection ftp = factory.getFtp();//获取ftp con
            return ftp.fileNames(path,keywork);
        } catch (IOException e) {
            System.err.println("=======>获取ftp目录下所有最近5分钟内生成的文件的文件名："+e.getMessage()+"<=======");
        }
        return new ArrayList<>();
    }

    public static boolean delFilename(String path,String filename) {
        try {
            //创建n个ftp链接
            FtpFactory factory = new FtpFactory();//连接FTP
            FtpConnection ftp = factory.getFtp();//获取ftp con
            return ftp.delectFile(path,filename);
        } catch (IOException e) {
            logger.error("delete the ftp file:path={},filename={}", 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) {
        FtpConnection ftp = new FtpConnection();//获取ftp con
        for(int retryIndex=0;retryIndex<5;retryIndex++) {
            Exception lastSocketException = null;
            try {
                String content = ftp.getFileContent(path, ftpFileName);
                return content;
            }
            catch (SocketException ex) {
                logger.error("SECURITY-ERROR-getFileContent-IO: get ftp file(path={},fileName={})exception", path, ftpFileName, ex);
                lastSocketException = ex;

                ThreadUtil.sleep(300);
            }
            catch (Exception e) {
                logger.error("SECURITY-ERROR-getFileContent: get ftp file(path={},fileName={})exception", path, ftpFileName, e);
            } finally {
                if(lastSocketException==null) {
                    try {
                        ftp.delectFile(path, ftpFileName);
                    } catch (Exception ex) {
                        logger.error("failed to delete file:path={};fileName={}", path, ftpFileName);
                    }
                }

                try {
                    ftp.disconnect();
                } catch (IOException e) {
                    logger.error("disconnect ftp exception", e);
                }
            }
        }

        return "";
    }

    public static String getFileContent(FtpConnection ftp,String path, String ftpFileName) {
        try {
            return ftp.getFileContent(path, ftpFileName);
        } catch (Exception e) {
            logger.error("fail to get ftp file(path={},fileName={}) with exception", path, ftpFileName, e);

            throw new RuntimeException("failed to get fileContent", e);
        }
    }

    public static void disConnect(FtpConnection ftp,String path, String ftpFileName){
        try {
            ftp.delectFile(path, ftpFileName);
            ftp.disconnect();
        } catch (IOException e) {
            logger.error("获取ftp文件发生异常", e);
        }
    }

    public static Collection<String> getFtpMetaFiles(FtpConnection ftp){
        //return ftp.getMetaFileNames("INJTLZ-",20);
        return getFiles(ftp, "INJTLZ-",20);
    }


    public static Collection<String> getDirectlyFiles(FtpConnection ftp,String filePrefix) {
       // return ftp.getMetaFileNames("IN-JTLZ-", 60);
        return ftp.getMetaFileNames(filePrefix, 60);
    }

    public static Collection<String> getFiles(FtpConnection ftp,String filePrefix,int limit)
    {
        return ftp.getMetaFileNames(filePrefix,limit);
    }
}
