package com.artfess.security.manager.impl;

import com.artfess.base.manager.impl.BaseManagerImpl;
import com.artfess.base.util.AuthenticationUtil;
import com.artfess.security.dao.BackupDatasourceDao;
import com.artfess.security.dao.BackupLogDao;
import com.artfess.security.manager.BackupDatasourceManager;
import com.artfess.security.model.BackupDatasource;
import com.artfess.security.model.BackupLog;
import com.artfess.security.util.SSHLinux;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 系统功能 --数据库备份管理-数据源配置表 服务实现类
 *
 * @author wh
 * @company wh
 * @since 2021-04-22
 */
@Service
public class BackupDatasourceManagerImpl extends BaseManagerImpl<BackupDatasourceDao, BackupDatasource> implements BackupDatasourceManager {
    @Autowired
    private BackupDatasourceDao mapper;

    @Autowired
    private BackupLogDao logMapper;

    //测试数据库连接
    public String testDB(String id) {
        BackupDatasource BackupDatasource = this.getById(id);
        try {
            boolean conn = checkConnection(BackupDatasource.getDbUrl(), BackupDatasource.getDbUser(), BackupDatasource.getDbPwd(), BackupDatasource.getDbDriver());
            if (conn) {
                return "连接成功！";
            } else {
                return "连接失败！";
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return "连接失败！" + e.getMessage();
        }
    }

    //测试服务器连接
    public String testSystem(String id) {
        BackupDatasource BackupDatasource = this.getById(id);
        try {
            String conn = "";
            if ("linux".equals(BackupDatasource.getSystemType())) {
                conn = SSHLinux.testConnect(BackupDatasource.getSystemIp(), 22, BackupDatasource.getSystemUser(), BackupDatasource.getSystemPwd());
            }
            if (conn.indexOf("LSB Version") != -1) {
                return "连接成功！";
            } else {
                return "连接失败！";
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return "连接失败！" + e.getMessage();
        }
    }

    //手动备份、还原数据库
    public String backUpDataBase(String id) {
        BackupDatasource BackupDatasource = this.getById(id);
        Integer port = 22;
        String ip = BackupDatasource.getSystemIp();
        String user = BackupDatasource.getSystemUser();
        String pwd = BackupDatasource.getSystemPwd();

        String cmd = BackupDatasource.getBackupCommond();
        //解析文件日期
        //mysqldump -uroot -p'artfess@023,.;' test > /opt/{yyyyMMdd}.sql
        cmd = getStrByCmd(cmd) + ".sql";
        String result = SSHLinux.exeCommand(ip, port, user, pwd, cmd);
        //记录备份日志
        String file = cmd.substring(cmd.lastIndexOf(">") + 1).trim();
        saveLog(id, file, "备份", result);
        return result;
    }

    //手动还原、还原数据库
    public String Reduction(String id) {
        //try {
        BackupLog BackupLog = this.logMapper.selectById(id);

        BackupDatasource BackupDatasource = this.getById(BackupLog.getSystemConfigId());
        Integer port = 22;
        String ip = BackupDatasource.getSystemIp();
        String user = BackupDatasource.getSystemUser();
        String pwd = BackupDatasource.getSystemPwd();

        String cmd = BackupDatasource.getReductionCommond();

        String file = BackupLog.getBackupFile();
        //解析文件日期
        //mysql -uroot -p'artfess@023,.;' test < /opt/{file}
        cmd = cmd.substring(0, cmd.lastIndexOf("<")) + " < " + file;
        String result = SSHLinux.exeCommand(ip, port, user, pwd, cmd);
        //记录备份日志
        saveLog(id, file, "还原", result);
        return result;
//        }catch (Exception e){
//            return "还原失败";
//        }
    }

    public void saveLog(String systemCopnfigId, String file, String type, String result) {
        BackupLog log = new BackupLog();
        log.setCreateTime(LocalDateTime.now());
        log.setSystemType(type);
        log.setSystemConfigId(systemCopnfigId);
        log.setBackupFile(file);
        log.setSystemResult(result);
        if ("还原".equals(type)) {
            log.setReductionTime(LocalDateTime.now());
            log.setReductionUserId(AuthenticationUtil.getCurrentUserId());
            log.setReductionOrgId(AuthenticationUtil.getCurrentUserMainOrgId());
            log.setReductionUser(AuthenticationUtil.getCurrentUsername());
        }
        this.logMapper.insert(log);
    }

    public static String getStrByCmd(String cmd) {
        Pattern p = Pattern.compile("\\{(.[^\\{\\}]*)\\}");
        Matcher m = p.matcher(cmd);
        StringBuffer sb = new StringBuffer();
        String dateFormat;
        synchronized (m) {
            if (m.find()) {
                dateFormat = m.group(1);
                m.appendReplacement(sb, getDateFormat(dateFormat, new Date()));
            }
        }
        return sb.toString();
    }

    /**
     * @param
     * @Description: 获取时间
     * @Return:
     * @Author: wh
     * @Date: 2020/5/15 10:25
     */
    private static String getDateFormat(String dateFormat, Date date) {
        SimpleDateFormat df = new SimpleDateFormat(dateFormat);
        return df.format(date);
    }

    public boolean checkConnection(String url, String userName, String pwd, String driver) {
        boolean isConnection = false;
        Connection con = null;
        try {
            Class.forName(driver);
            System.out.println("数据库驱动加载成功");
        } catch (ClassNotFoundException e) {
            log.error("数据库驱动加载失败" + e.getMessage());
        }
        try {
            con = DriverManager.getConnection(url, userName, pwd);
            isConnection = true;
            System.out.println("数据库连接成功");
        } catch (SQLException e) {
            log.error("数据库链接失败" + e.getMessage());
        } finally {
            if (con != null) {
                try {
                    con.close();
                } catch (SQLException e1) {
                    log.error(e1.getMessage(), e1);
                }
            }
        }
        return isConnection;
    }
}
