package com.hzya.frame.plugin.BackUpDatabase.plugin;

import com.alibaba.fastjson.JSONObject;
import com.hzya.frame.base.PluginBaseEntity;
import com.hzya.frame.web.entity.BaseResult;
import com.hzya.frame.web.entity.JsonResultEntity;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;
import org.apache.commons.net.ftp.FTPClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;


/**
 * 主数据模版(MdmModule)表服务接口
 *
 * @author makejava
 * @since 2024-06-18 10:33:32
 */
public class BackUpDatabaseInitializer extends PluginBaseEntity {
    Logger logger = LoggerFactory.getLogger(BackUpDatabaseInitializer.class);

    @Override
    public void initialize() {
        logger.info(getPluginLabel() + "執行初始化方法initialize()");
    }

    @Override
    public void destroy() {
        logger.info(getPluginLabel() + "執行銷毀方法destroy()");
    }

    @Override
    public String getPluginId() {
        return "BackUpDatabasePlugin";
    }

    @Override
    public String getPluginName() {
        return "数据库备份下发";
    }

    @Override
    public String getPluginLabel() {
        return "BackUpDatabasePlugin";
    }

    @Override
    public String getPluginType() {
        return "1";
    }

    @Value("${database.filePase:}")
    private String filePase;//文件保存路径

    @Value("${database.fileName:data.sql}")
    private String fileName;//文件保存名称

    @Value("${database.databaseName:}")
    private String databaseName;//库名

    @Value("${database.host:}")
    private String host;//地址

    @Value("${database.port:}")
    private String port;//端口

    @Value("${database.username:}")
    private String username;//用户名

    @Value("${database.password:}")
    private String password;//密码


    @Value("${sftp.host:}")
    private String sftpHost;

    @Value("${sftp.port:}")
    private Integer sftpPort;

    @Value("${sftp.username:}")
    private String sftpUsername;

    @Value("${sftp.password:}")
    private String sftpPassword;

    @Value("${sftp.filePase:}")
    private String sftpFilePase;


    private ChannelSftp sftp = null;
    private Session sshSession = null;

    @Override
    public JsonResultEntity executeBusiness(JSONObject requestJson) {
        try {
            if(filePase == null || "".equals(filePase)
                || databaseName == null || "".equals(databaseName)
                || fileName == null || "".equals(fileName)
                || host == null || "".equals(host)
                || port == null || "".equals(port)
                || username == null || "".equals(username)
                || password == null || "".equals(password)
            ){
                return BaseResult.getSuccessMessageEntity("系统参数未配置不执行，数据库备份");
            }
            //查找是否存在当天数据库
            //格式化日期
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String data = sdf.format(new Date());
            //当天路径
            String nowDatabasePase = filePase + File.separator + data;
            //不判断文件是否存在，直接执行
            if(!backFile(nowDatabasePase)){
                return BaseResult.getFailureMessageEntity("备份失败");
            }
            //判断是否有sftp配置，有的备份，没有的不备份
            if(sftpHost != null && !"".equals(sftpHost)
                && sftpPort != null && !"".equals(sftpPort)
                && sftpUsername != null && !"".equals(sftpUsername)
                && sftpPassword != null && !"".equals(sftpPassword)
                && sftpFilePase != null && !"".equals(sftpFilePase)
            ){
                String sftpnowDatabasePase = sftpFilePase + File.separator + data;
                if(!sendFile(nowDatabasePase,sftpnowDatabasePase)){
                    return BaseResult.getFailureMessageEntity("备份失败");
                }
            }
            logger.info("执行成功");
            return BaseResult.getSuccessMessageEntity("执行成功");
        } catch (Exception e) {
            logger.error("执行失败{}", e.getMessage());
            return BaseResult.getFailureMessageEntity("备份失败");
        }
    }

    private boolean backFile(String nowDatabasePase) {
        try {
            // 构建 mysqldump 命令
            ProcessBuilder processBuilder = new ProcessBuilder(
                    "mysqldump",
                    "--ssl-mode=DISABLED",
                    "-h", host,
                    "-u", username,
                    "-p" + password,
                    "-P" + port,
                    databaseName);
            // 启动进程并获取输入流
            Process process = processBuilder.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            File f  = creatFile(nowDatabasePase,fileName);
            // 将备份内容写入文件
            FileWriter writer = new FileWriter(f);
            String line;
            while ((line = reader.readLine())!= null) {
                writer.write(line + "\n");
            }
            // 关闭资源
            reader.close();
            writer.close();
            process.waitFor();
            logger.info("文件备份成功路径："+nowDatabasePase+ File.separator +fileName);
            return true;
        } catch (IOException | InterruptedException e) {
            logger.info("文件备份失败："+e.getMessage());
            return false;
        }
    }
    /**
     * @Author lvleigang
     * @Description  创建目录及文件
     * @Date 8:59 上午 2024/10/22
     * @param filePath
     * @param fileName
     * @return java.io.File
     **/
    public File creatFile(String filePath, String fileName) {
        File folder = new File(filePath);
        //文件夹路径不存在
        if (!folder.exists()) {
            boolean mkdirs = folder.mkdirs();
        }
        // 如果文件不存在就创建
        File file = new File(filePath + File.separator + fileName);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                logger.error("创建备份文件失败："+e.getMessage());
            }
        }
        return file;
    }

    private boolean sendFile(String localFilePath,String remoteFileName) {
        try {
            connect();
            uploadFile(remoteFileName,fileName,localFilePath,fileName);
            disconnect();
            return true;
        } catch (Exception e) {
            logger.error("sftp文件上传失败:"+e.getMessage());
            return false;
        }
    }

    public void connect() {
        try {
            JSch jsch = new JSch();
            jsch.getSession(sftpUsername, sftpHost, sftpPort);
            sshSession = jsch.getSession(sftpUsername, sftpHost, sftpPort);
            if (logger.isInfoEnabled()) {
                logger.info("Session created.");
            }
            sshSession.setPassword(sftpPassword);
            Properties sshConfig = new Properties();
            sshConfig.put("StrictHostKeyChecking", "no");
            sshSession.setConfig(sshConfig);
            sshSession.connect();
            if (logger.isInfoEnabled()) {
                logger.info("Session connected.");
            }
            Channel channel = sshSession.openChannel("sftp");
            channel.connect();
            if (logger.isInfoEnabled()) {
                logger.info("Opening Channel.");
            }
            sftp = (ChannelSftp) channel;
            if (logger.isInfoEnabled()) {
                logger.info("Connected to " + host + ".");
            }
        } catch (Exception e) {
        }
    }

    /**
     * 关闭连接
     */
    public void disconnect() {
        if (this.sftp != null) {
            if (this.sftp.isConnected()) {
                this.sftp.disconnect();
                if (logger.isInfoEnabled()) {
                    logger.info("sftp is closed already");
                }
            }
        }
        if (this.sshSession != null) {
            if (this.sshSession.isConnected()) {
                this.sshSession.disconnect();
                if (logger.isInfoEnabled()) {
                    logger.info("sshSession is closed already");
                }
            }
        }
    }

    /**
     * 上传单个文件
     *
     * @param remotePath：远程保存目录
     * @param remoteFileName：保存文件名
     * @param localPath：本地上传目录(以路径符号结束)
     * @param localFileName：上传的文件名
     * @return
     */
    public boolean uploadFile(String remotePath, String remoteFileName, String localPath, String localFileName) {
        FileInputStream in = null;
        try {
            createDir(remotePath);
            File file = new File(localPath + File.separator +  localFileName);
            in = new FileInputStream(file);
            sftp.put(in, remoteFileName, 65536);
            return true;
        } catch (FileNotFoundException e) {
        } catch (SftpException e) {
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                }
            }
        }
        return false;
    }

    /**
     * 创建目录
     *
     * @param createpath
     * @return
     */
    public boolean createDir(String createpath) {
        try {
            if (isDirExist(createpath)) {
                this.sftp.cd(createpath);
                return true;
            }
            String pathArry[] = createpath.split("/");
            StringBuffer filePath = new StringBuffer("/");
            for (String path : pathArry) {
                if (path.equals("")) {
                    continue;
                }
                filePath.append(path + "/");
                if (isDirExist(filePath.toString())) {
                    sftp.cd(filePath.toString());
                } else {
                    // 建立目录
                    sftp.mkdir(filePath.toString());
                    // 进入并设置为当前目录
                    sftp.cd(filePath.toString());
                }

            }
            this.sftp.cd(createpath);
            return true;
        } catch (SftpException e) {
        }
        return false;
    }

    /**
     * 判断目录是否存在
     *
     * @param directory
     * @return
     */
    public boolean isDirExist(String directory) {
        boolean isDirExistFlag = false;
        try {
            SftpATTRS sftpATTRS = sftp.lstat(directory);
            isDirExistFlag = true;
            return sftpATTRS.isDir();
        } catch (Exception e) {
            if (e.getMessage().toLowerCase().equals("no such file")) {
                isDirExistFlag = false;
            }
        }
        return isDirExistFlag;
    }



    /**
     * 如果目录不存在就创建目录
     *
     * @param path
     */
    public void mkdirs(String path) {
        File f = new File(path);

        String fs = f.getParent();

        f = new File(fs);

        if (!f.exists()) {
            f.mkdirs();
        }
    }





}
