package com.bcxin.signature.util.ftp;

import com.bcxin.signature.config.FileWriteConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.*;
import java.net.UnknownHostException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * <b> ftp客户端 </b>
 * @author ZXF
 * @create 2023/07/07 0007 13:51
 * @version
 * @注意事项 </b>
 */
@Slf4j
public class FtpWriteConnection {

    private FTPClient ftp = new FTPClient();

    private boolean is_connected = false;

    /**
     * 构造函数
     */
    public FtpWriteConnection() {
        is_connected = false;
        ftp.setDefaultTimeout(FileWriteConfig.defaultTimeoutSecond * 1000);
        ftp.setConnectTimeout(FileWriteConfig.connectTimeoutSecond * 1000);
        ftp.setDataTimeout(FileWriteConfig.dataTimeoutSecond * 1000);
        try {
            initConnect(FileWriteConfig.getHost(), FileWriteConfig.getPort(), FileWriteConfig.getUserName(), FileWriteConfig.getPassword());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化连接
     *
     * @param host
     * @param port
     * @param user
     * @param password
     * @throws IOException
     */
    private void initConnect(String host, int port, String user, String password) throws IOException {
        try {
            if(!ftp.isConnected()){
                ftp.connect(host, port);
            }
        } catch (UnknownHostException ex) {
            throw new IOException("Can't find FTP server '" + host + "'");
        }
        //被动模式
        ftp.enterLocalPassiveMode();
        int reply = ftp.getReplyCode();//220 连接成功
        if (!FTPReply.isPositiveCompletion(reply)) {
            disconnect();
            throw new IOException("Can't connect to server '" + host + "'");

        }
        if (!ftp.login(user, password)) {
            is_connected = false;
            disconnect();
            throw new IOException("Can't login to server '" + host + "'");
        } else {
            is_connected = true;
        }
    }

    public static boolean hasChineseUsingRegex(String str) {
        return str.matches(".*[\u4e00-\u9fa5]+.*");
    }

    public boolean uploadBase64(String path, String ftpFileName, String base64Content) throws IOException {
        boolean is = false;
        // 检查Base64内容是否为空
        if (base64Content == null || base64Content.isEmpty()) {
            throw new IOException("Can't upload. The base64 content is empty.");
        }
        // 转换路径和文件名，防止设置工作路径出错
        conv(path,ftpFileName);
        if(hasChineseUsingRegex(ftpFileName)){
            return false;
        }
        if(StringUtils.isNotEmpty(path)){
            path = new String(path.getBytes("GBK"), "iso-8859-1");
            // 设置工作路径
            setWorkingDirectory(path);
        }
        ftpFileName = new String(ftpFileName.getBytes("GBK"), "iso-8859-1");

        // 将Base64字符串解码为字节数组
//        byte[] decodedBytes = Base64.getDecoder().decode(base64Content);
        byte[] decodedBytes = base64Content.getBytes();

        // 上传
        try (InputStream in = new ByteArrayInputStream(decodedBytes)) {
            String filePath = path + "/" + ftpFileName;
            filePath = filePath.replace("\\", "/");
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            // 保存文件
            is = ftp.storeFile(filePath, in);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return is;
    }

    private static void conv(String path,String ftpFileName){
        ftpFileName = ftpFileName.startsWith("/")?ftpFileName:"/"+ftpFileName;
        Path sourcePath = Paths.get(path+ftpFileName);
        if(sourcePath.getParent() !=null){
            path = sourcePath.getParent().toAbsolutePath().toString();
        }
        ftpFileName = sourcePath.getFileName().toString();
    }

    /**
     * 检查 FTP 服务器上的文件是否存在
     *
     * @param filePath 文件路径
     * @return 文件存在返回 true，否则返回 false
     * @throws IOException
     */
    private boolean fileExists(String filePath) throws IOException {
        // 获取文件的父目录
        String parentDir = new File(filePath).getParent();
        // 获取文件名
        String fileName = new File(filePath).getName();

        // 获取文件列表
        FTPFile[] files = ftp.listFiles();

        // 检查文件列表中是否存在指定的文件
        for (FTPFile file : files) {
            if (file.getName().equals(fileName)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 获取ftp目录下所有最近5分钟内生成的文件的文件名，返回文件名列表
     *
     * @param path ftp操作目录
     * @return 最近5分钟内生成的文件名列表
     * @throws IOException
     */
    public List<String> fileNames(String path,String keywork) throws IOException {
        if(StringUtils.isEmpty(keywork)){
            keywork = "IN-";
        }
        if(StringUtils.isNotEmpty(path)){
            path = new String(path.getBytes("GBK"), "iso-8859-1");
            System.err.println("=======>获取ftp目录下所有文件业务节点：001<=======");
            // 设置工作路径
            setWorkingDirectory(path);
        }
        System.err.println("=======>获取ftp目录下所有文件业务,ftp路径："+path+",关键字："+keywork+"<=======");
        System.err.println("=======>获取ftp目录下所有文件业务节点：002<=======");

        List<String> recentFiles = new ArrayList<>();
        FTPFile[] files = ftp.listFiles();
        System.err.println("=======>获取ftp目录下所有文件业务节点：003<=======");

        long currentTime = System.currentTimeMillis();
        long fiveMinutesAgo = currentTime - (5 * 60 * 1000); // 5 minutes ago in milliseconds

        System.err.println("=======>获取ftp目录下所有文件的数量："+files.length+"<=======");
        for (FTPFile file : files) {
            System.err.println("=======>获取ftp目录下所有文件的名称.filename："+file.getName()+"<=======");
            //转utc 时间加8小时
            Long fileTime = file.getTimestamp().getTimeInMillis()+file.getTimestamp().getTimeZone().getOffset(0);
            if (file.isFile() && fileTime >= fiveMinutesAgo && file.getName().startsWith(keywork)) {
                System.err.println("=======>获取ftp目录下所有文件业务有效文件名："+file.getName()+"<=======");
                recentFiles.add(file.getName());
            }
        }
        System.err.println("=======>获取ftp目录下所有最近5分钟内生成的文件的数量："+recentFiles.size()+"<=======");

        return recentFiles;
    }

    /**
     * 关闭连接
     *
     * @throws IOException
     */
    public void disconnect() throws IOException {
        if (ftp.isConnected()) {
            try {
                ftp.logout();
                ftp.disconnect();
                is_connected = false;
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * 设置工作路径
     *
     * @param dir
     * @return
     */
    private boolean setWorkingDirectory(String dir) {
        if (!is_connected) {
            return false;
        }
        //如果目录不存在创建目录
        try {
            if (createDirecroty(dir)) {
                return ftp.changeWorkingDirectory(dir);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;

    }

    /**
     * 是否连接
     *
     * @return
     */
    public boolean isConnected() {
        return is_connected;
    }

    /**
     * 创建目录
     *
     * @param remote
     * @return
     * @throws IOException
     */
    private boolean createDirecroty(String remote) throws IOException {
        if(StringUtils.isEmpty(remote)){
            return false;
        }
        boolean success = true;
        String directory = remote.substring(0, remote.lastIndexOf("/") + 1);
        // 如果远程目录不存在，则递归创建远程服务器目录
        if (!directory.equalsIgnoreCase("/") && !ftp.changeWorkingDirectory(new String(directory))) {
            int start = 0;
            int end = 0;
            if (directory.startsWith("/")) {
                start = 1;
            } else {
                start = 0;
            }
            end = directory.indexOf("/", start);
            while (true) {
                String subDirectory = new String(remote.substring(start, end));
                if (!ftp.changeWorkingDirectory(subDirectory)) {
                    if (ftp.makeDirectory(subDirectory)) {
                        ftp.changeWorkingDirectory(subDirectory);
                    } else {
                        log.error("mack directory error :/" + subDirectory);
                        return false;
                    }
                }
                start = end + 1;
                end = directory.indexOf("/", start);
                // 检查所有目录是否创建完毕
                if (end <= start) {
                    break;
                }
            }
        }
        return success;
    }
}
