package com.njzscloud.common.mp.support;

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.njzscloud.common.mp.config.DbTunnelProperties;

import java.io.File;

import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Slf4j
public class DBTunnel {

    private final DbTunnelProperties dbTunnelProperties;
    private JSch jsch;
    private Session session;
    private ScheduledExecutorService heartbeatExecutor;

    public DBTunnel(DbTunnelProperties dbTunnelProperties) {
        this.dbTunnelProperties = dbTunnelProperties;
        if (dbTunnelProperties.isEnable()) {
            log.info("数据库 SSH 隧道已启用");
            connect();
            startHeartbeat();
        }
    }

    private synchronized void connect() {
        try {
            if (isConnected()) {
                return;
            }

            DbTunnelProperties.SSHProperties ssh = dbTunnelProperties.getSsh();
            String credentials = ssh.getCredentials();
            String passphrase = ssh.getPassphrase();
            String user = ssh.getUser();
            String host = ssh.getHost();
            int port = ssh.getPort();
            int localPort = ssh.getLocalPort();
            DbTunnelProperties.DBProperties db = dbTunnelProperties.getDb();
            String dbHost = db.getHost();
            int dbPort = db.getPort();

            jsch = new JSch();
            // 使用私钥认证
            File keyFile = new File(credentials);
            if (!keyFile.exists()) {
                throw new RuntimeException("私钥文件不存在: " + credentials);
            }

            if (passphrase != null) {
                jsch.addIdentity(credentials, passphrase);
            } else {
                jsch.addIdentity(credentials);
            }

            // 创建SSH会话
            session = jsch.getSession(user, host, port);
            session.setConfig("StrictHostKeyChecking", "no"); // 禁用主机密钥检查

            // 设置保持活动状态
            session.setServerAliveInterval(60000); // 每分钟发送一次保持活动的数据包
            session.setServerAliveCountMax(3); // 允许3次失败

            session.connect();

            // 设置端口转发 (本地端口 -> 远程数据库)
            session.setPortForwardingL(localPort, dbHost, dbPort);
            log.info("SSH 隧道已成功连接并转发端口 {} -> {}:{}", localPort, dbHost, dbPort);
        } catch (JSchException e) {
            log.error("SSH 隧道连接失败", e);
            throw new RuntimeException("SSH 隧道连接失败", e);
        }
    }

    private void startHeartbeat() {
        heartbeatExecutor = Executors.newSingleThreadScheduledExecutor();
        heartbeatExecutor.scheduleAtFixedRate(() -> {
            try {
                if (!isConnected()) {
                    log.warn("SSH 隧道连接已断开，尝试重新连接...");
                    connect();
                }
            } catch (Exception e) {
                log.error("SSH 隧道心跳检测失败", e);
            }
        }, 30, 30, TimeUnit.SECONDS); // 每30秒检查一次连接状态
    }

    public boolean isConnected() {
        return session != null && session.isConnected();
    }

    public void close() {
        if (heartbeatExecutor != null) {
            heartbeatExecutor.shutdownNow();
        }

        if (session != null && session.isConnected()) {
            session.disconnect();
            log.info("SSH隧道已关闭");
        }
    }
}
