package com.yfd.platform.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.net.ftp.FTPSClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

@Component
@Slf4j
public class FtpClient {
    @Value("${parentserver.serverip}")
    private String ftp_ip;

    @Value("${parentserver.ftpport}")
    private int ftp_port;

    @Value("${parentserver.ftpusername}")
    private String ftp_userName;

    @Value("${parentserver.ftppassword}")
    private String ftp_userPassword;

    TrustManager[] trustManager = new TrustManager[] { new X509TrustManager() {

        public void checkClientTrusted(X509Certificate[] chain,
                                       String authType) throws CertificateException {
            // TODO Auto-generated method stub

        }

        public void checkServerTrusted(X509Certificate[] chain,
                                       String authType) throws CertificateException {
            // TODO Auto-generated method stub

        }

        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }

    } };


    public boolean uploadFile(String localFileName, String remoteFileName) throws Exception {
        log.info("进入uploadFile上传方法");
        boolean flag = false;
        // 创建SSL上下文
        SSLContext sslContext = SSLContext.getInstance("TLS");
        // 自定义证书，忽略已过期证书
//        TrustManager[] trustAllCerts = new TrustManager[1];
//        TrustManager tm = nesendRobotCommand MyTrustManager();
//        trustAllCerts[0] = tm;
        // 初始化SSL上下文，使用自定义的信任管理器
        sslContext.init(null, trustManager, new SecureRandom());

        // 设置FTP客户端使用的SSL上下文
        // 创建客户端，选择Implicit模式
        FTPSClient ftpClient = new FTPSClient(true,sslContext);

        ftpClient.setNeedClientAuth(false);
        ftpClient.setControlEncoding("UTF-8");
        try {
            int reply;
            log.info("建立ftp服务连接");
            ftpClient.connect(ftp_ip, ftp_port);// 连接FTP服务器
            log.info("登录ftp服务");
            ftpClient.login(ftp_userName, ftp_userPassword);// 登录
            reply = ftpClient.getReplyCode();
            log.info("登录ftp服务返回状态码为：" + reply);
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                return flag;
            }
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            //设置为被动模式
            ftpClient.enterLocalPassiveMode();
            //originFilePath就是上传文件的文件名，建议使用生成的唯一命名，中文命名最好做转码
            // 创建一个File对象，指定要读取的文件路径
            File file = new File(localFileName);
            // 创建一个FileInputStream对象，传入File对象
            InputStream input = new FileInputStream(file);
            String remotepath = StrUtil.subBefore(remoteFileName, "/", true);
            //remotepath= "/aaa/bbb";
            if (remotepath.contains("/")) {
                log.info("===========================================创建文件目录===========================================");
                boolean b = mkdirPath(remotepath, ftpClient);
            }
            String utf8RemotePath = new String(remoteFileName.getBytes("UTF-8"), "ISO-8859-1");
            boolean a = ftpClient.storeFile(utf8RemotePath, input);
            log.info("要上传的原始文件名为：" + remoteFileName + ", 上传结果：" + a);
            input.close();
            ftpClient.logout();
            flag = true;
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException ignored) {

                }
            }
        }
        return flag;
    }

    public boolean uploadFile(String ip, String port, String username, String password, String filePath, String roPath) throws NoSuchAlgorithmException, KeyManagementException {
        log.info("进入uploadFile上传方法");
        boolean flag = false;
        // 创建SSL上下文
        SSLContext sslContext = SSLContext.getInstance("TLS");
        // 自定义证书，忽略已过期证书
        TrustManager[] trustAllCerts = new TrustManager[1];
        TrustManager tm = new MyTrustManager();
        trustAllCerts[0] = tm;
        // 初始化SSL上下文，使用自定义的信任管理器
        sslContext.init(null, trustAllCerts, null);
        // 设置FTP客户端使用的SSL上下文
        // 创建客户端，选择Implicit模式
        FTPSClient ftpClient = new FTPSClient(true,sslContext);
        ftpClient.setNeedClientAuth(false);
        ftpClient.setControlEncoding("gbk");
        try {
            int reply;
            log.info("建立ftp服务连接");
            ftpClient.connect(ip, Integer.parseInt(port));// 连接FTP服务器
            log.info("登录ftp服务");
            ftpClient.login(username, password);// 登录
            reply = ftpClient.getReplyCode();
            log.info("登录ftp服务返回状态码为：" + reply);
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                return flag;
            }
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            //设置为被动模式
            ftpClient.enterLocalPassiveMode();
            //originFilePath就是上传文件的文件名，建议使用生成的唯一命名，中文命名最好做转码
            // 创建一个File对象，指定要读取的文件路径
            File file = new File(filePath);
            // 创建一个FileInputStream对象，传入File对象
            InputStream input = new FileInputStream(file);
            String remotepath = StrUtil.subBefore(roPath, "/", true);
            //remotepath= "/aaa/bbb";
            if (remotepath.contains("/")) {
                boolean b = mkdirPath(remotepath, ftpClient);
            }
            boolean a = ftpClient.storeFile(roPath, input);
            log.info("要上传的原始文件名为：" + roPath + ", 上传结果：" + a);
            input.close();
            ftpClient.logout();
            flag = true;
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException ignored) {

                }
            }
        }
        return flag;
    }

    public boolean deleteFile(String filename) throws Exception {
        log.info("进入uploadFile上传方法");
        boolean flag = false;
        // 创建SSL上下文
        SSLContext sslContext = SSLContext.getInstance("TLS");
        // 自定义证书，忽略已过期证书
        TrustManager[] trustAllCerts = new TrustManager[1];
        TrustManager tm = new MyTrustManager();
        trustAllCerts[0] = tm;
        // 初始化SSL上下文，使用自定义的信任管理器
        sslContext.init(null, trustAllCerts, null);
        // 设置FTP客户端使用的SSL上下文
        // 创建客户端，选择Implicit模式
        FTPSClient ftpClient = new FTPSClient(true, sslContext);
        ftpClient.setNeedClientAuth(false);
        ftpClient.setControlEncoding("UTF-8");
        try {
            // 连接FTP服务器
            ftpClient.connect(ftp_ip, ftp_port);
            // 登录FTP服务器
            ftpClient.login(ftp_userName, ftp_userPassword);
            // 验证FTP服务器是否登录成功
            int replyCode = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                return flag;
            }
            // 切换FTP目录
            ftpClient.dele(filename);
            ftpClient.logout();
            flag = true;
        } catch (Exception e) {
            log.error(e.getMessage());;
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.logout();
                } catch (IOException e) {

                }
            }
        }
        return flag;
    }

    public void downloadFile(String remoteFilePath, String localFilePath) throws IOException {
        // 第二个参数true表示使用隐式SSL
        FTPSClient ftps = new FTPSClient(true);
        ftps.connect(ftp_ip, ftp_port);

        if (!FTPReply.isPositiveCompletion(ftps.getReplyCode())) {
            ftps.disconnect();
            throw new IOException("连接ftp失败");
        }

        if (!ftps.login(ftp_userName, ftp_userPassword)) {
            ftps.logout();
            ftps.disconnect();
            throw new IOException("FTP登录失败");
        }

        // 设置为被动模式
        ftps.enterLocalPassiveMode();
        // 设置文件类型
        ftps.setFileType(FTPClient.BINARY_FILE_TYPE);
        FileUtil.touch(localFilePath);
        String utf8RemotePath = new String(remoteFilePath.getBytes("UTF-8"), "ISO-8859-1");

        // 下载文件
        try (OutputStream outputStream = new FileOutputStream(localFilePath)) {
            boolean success = ftps.retrieveFile(utf8RemotePath, outputStream);
            if (!success) {
                throw new IOException("没有发现文件 " + remoteFilePath);
            }
        }

        ftps.logout();
        ftps.disconnect();
    }

    public boolean uploadFileNew(String localFileName, String remoteFileName) throws Exception {
        log.info("进入uploadFile上传方法");
        // 第二个参数true表示使用隐式SSL
        FTPSClient ftps = new FTPSClient(true);
        ftps.connect(ftp_ip, ftp_port);

        if (!FTPReply.isPositiveCompletion(ftps.getReplyCode())) {
            ftps.disconnect();
            throw new IOException("连接ftp失败");
        }

        if (!ftps.login(ftp_userName, ftp_userPassword)) {
            ftps.logout();
            ftps.disconnect();
            throw new IOException("FTP登录失败");
        }

        // 设置为被动模式
        ftps.enterLocalPassiveMode();
        // 设置文件类型
        ftps.setFileType(FTPClient.BINARY_FILE_TYPE);
//        FileUtil.touch(localFileName);
        String utf8RemotePath = new String(remoteFileName.getBytes("UTF-8"), "ISO-8859-1");
        //originFilePath就是上传文件的文件名，建议使用生成的唯一命名，中文命名最好做转码
        // 创建一个File对象，指定要读取的文件路径
        File file = new File(localFileName);
        // 创建一个FileInputStream对象，传入File对象
        InputStream input = new FileInputStream(file);
        String remotepath = StrUtil.subBefore(utf8RemotePath, "/", true);
        //remotepath= "/aaa/bbb";
        if (remotepath.contains("/")) {
            mkdirPath(remotepath, ftps);
        }
        boolean a = ftps.storeFile(utf8RemotePath, input);
        log.info("要上传的原始文件名为：" + utf8RemotePath + ", 上传结果：" + a);
        input.close();
        ftps.logout();
        return true;
    }

    public String readFileContent(String remoteFilePath) {
        FTPSClient ftpClient = new FTPSClient(true);
        ftpClient.setNeedClientAuth(false);
        ftpClient.enterLocalPassiveMode();
        ftpClient.setControlEncoding("UTF-8");
        StringBuilder xmlContent = new StringBuilder();
        try {
            // 连接FTP服务器
            ftpClient.connect(ftp_ip, ftp_port);
            // 登录FTP服务器
            ftpClient.login(ftp_userName, ftp_userPassword);
            // 验证FTP服务器是否登录成功
            int replyCode = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                return "";
            }
            // 获取文件内容
            InputStream inputStream = ftpClient.retrieveFileStream(remoteFilePath);
            if (inputStream != null) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                String line;

                while ((line = reader.readLine()) != null) {
                    xmlContent.append(line);
                }
                reader.close();
                inputStream.close();

            }
            ftpClient.logout();
            log.info("文件获取完成！！！");
        } catch (Exception e) {
            log.error(e.getMessage());;
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.logout();
                } catch (IOException ignored) {

                }
            }
        }
        return xmlContent.toString();
    }

    /**
     * @param path ftp服务器文件目录
     * @param ftp  FTPClient对象
     * @return 创建状态
     */
    public boolean mkdirPath(String path, FTPClient ftp) {
        try {
            String directory = path.endsWith("/") ? path : path + "/";
            if (!directory.equalsIgnoreCase("/") && !ftp.changeWorkingDirectory(directory)) {
                // 如果远程目录不存在，则递归创建远程服务器目录
                int start = 0;
                int end;
                if (directory.startsWith("/")) {
                    start = 1;
                }
                end = directory.indexOf("/", start);
                do {
                    String subDirectory = path.substring(0, end);
                    if (!ftp.changeWorkingDirectory(subDirectory)) {
                        if (ftp.makeDirectory(subDirectory)) {
                            if (!ftp.changeWorkingDirectory(subDirectory)) {
                                return false;
                            }
                        } else {
                            return false;
                        }
                    }
                    start = end + 1;
                    end = directory.indexOf("/", start);
                } while (end > start);
            }
            return true;
        } catch (Exception exception) {
            log.error(exception.getMessage());
            return false;
        }
    }

    public boolean uploadfileSystem(String ip,String port,String name,String password,String localFileName, String remoteFileName) throws IOException {

        log.info("进入uploadFile上传方法");
        // 第二个参数true表示使用隐式SSL
        FTPSClient ftps = new FTPSClient(true);
        ftps.connect(ip, NumberUtil.parseInt(port));

        if (!FTPReply.isPositiveCompletion(ftps.getReplyCode())) {
            ftps.disconnect();
            throw new IOException("连接ftp失败");
        }

        if (!ftps.login(name, password)) {
            ftps.logout();
            ftps.disconnect();
            throw new IOException("FTP登录失败");
        }

        // 设置为被动模式
        ftps.enterLocalPassiveMode();
        // 设置文件类型
        ftps.setFileType(FTPClient.BINARY_FILE_TYPE);
//        FileUtil.touch(localFileName);
        String utf8RemotePath = new String(remoteFileName.getBytes("UTF-8"), "ISO-8859-1");
        //originFilePath就是上传文件的文件名，建议使用生成的唯一命名，中文命名最好做转码
        // 创建一个File对象，指定要读取的文件路径
        File file = new File(localFileName);
        // 创建一个FileInputStream对象，传入File对象
        InputStream input = new FileInputStream(file);
        String remotepath = StrUtil.subBefore(utf8RemotePath, "/", true);
        //remotepath= "/aaa/bbb";
        if (remotepath.contains("/")) {
            mkdirPath(remotepath, ftps);
        }
        boolean a = ftps.storeFile(utf8RemotePath, input);
        log.info("要上传的原始文件名为：" + utf8RemotePath + ", 上传结果：" + a);
        input.close();
        ftps.logout();
        return true;
    }
}
