package main

import (
	"bytes"
	"flag"
	"fmt"
	"log"
	"os"
	"syscall"

	"golang.org/x/crypto/ssh"
	"golang.org/x/term"
)

// 通过 SSH 执行命令
func runSSHCommand(config SSHConfig, command string) (string, error) {
	// 创建 SSH 配置
	var authMethods []ssh.AuthMethod

	// 使用密码认证
	if config.Password != "" {
		authMethods = append(authMethods, ssh.Password(config.Password))
	}

	// 使用私钥认证
	if config.PrivateKey != "" {
		key, err := os.ReadFile(config.PrivateKey)
		if err != nil {
			return "", fmt.Errorf("failed to read private key file: %w", err)
		}

		var signer ssh.Signer
		if config.Passphrase != "" {
			// 使用密码解锁私钥
			signer, err = ssh.ParsePrivateKeyWithPassphrase(key, []byte(config.Passphrase))
		} else {
			// 无密码的私钥
			signer, err = ssh.ParsePrivateKey(key)
		}

		if err != nil {
			return "", fmt.Errorf("failed to parse private key: %w", err)
		}

		authMethods = append(authMethods, ssh.PublicKeys(signer))
	}

	if len(authMethods) == 0 {
		return "", fmt.Errorf("no authentication method provided")
	}

	sshConfig := &ssh.ClientConfig{
		User:            config.User,
		Auth:            authMethods,
		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 跳过主机密钥验证，生产环境中建议替换为可信的回调函数
	}

	// 连接到远程服务器
	address := fmt.Sprintf("%s:%d", config.Host, config.Port)
	client, err := ssh.Dial("tcp", address, sshConfig)
	if err != nil {
		return "", fmt.Errorf("failed to dial: %w", err)
	}
	defer client.Close()

	// 创建会话
	session, err := client.NewSession()
	if err != nil {
		return "", fmt.Errorf("failed to create session: %w", err)
	}
	defer session.Close()

	// 执行命令
	var stdout, stderr bytes.Buffer
	session.Stdout = &stdout
	session.Stderr = &stderr

	if err := session.Run(command); err != nil {
		return "", fmt.Errorf("执行命令失败: %w. stderr: %s", err, stderr.String())
	}
	if stderr.Len() > 0 {
		log.Printf("stderr: %s", stderr.String())
	}
	return stdout.String(), nil

}

func _ssh() (string, error) {
	// 校验必需参数
	if *h == "" || *u == "" || *c == "" || (*e == "" && *k == "") {
		fmt.Println("Error: Missing required parameters")
		flag.Usage()
		os.Exit(1)
	}

	// 如果使用私钥且需要密码解锁，则提示用户输入密码
	var passphrase string
	if *k != "" {
		fmt.Print("Enter passphrase for private key: ")
		bytePassword, err := term.ReadPassword(int(syscall.Stdin))
		if err != nil {
			log.Printf("Failed to read passphrase: %v", err)
		}
		passphrase = string(bytePassword)
		fmt.Println()
	}

	// 构造 SSH 配置
	config := SSHConfig{
		Host:       *h,
		Port:       *p,
		User:       *u,
		Password:   *e,
		PrivateKey: *k,
		Passphrase: passphrase,
	}

	// 执行命令
	output, err := runSSHCommand(config, *c)
	if err != nil {
		log.Printf("Error: %v", err)
	}

	return output, err
}
