//go:build with_gvisor && unix && !android && !ios

package tailssh

import (
	"os"
	"path/filepath"

	"github.com/sagernet/sing-box/adapter"
	E "github.com/sagernet/sing/common/exceptions"
)

func selectShellBackend(platformInterface adapter.PlatformInterface) shellBackend {
	if platformInterface != nil && platformInterface.UsePlatformShell() {
		return &platformShellBackend{platform: platformInterface}
	}
	return &directShellBackend{}
}

func CheckServerSupport(platformInterface adapter.PlatformInterface) (string, error) {
	if platformInterface != nil && platformInterface.UnderNetworkExtension() {
		if !platformInterface.UsePlatformShell() {
			return "", E.New("SSH server is not supported in the App Store version of sing-box")
		}
		err := platformInterface.CheckPlatformShell()
		if err != nil {
			return "", E.Cause(err, "missing Root Helper")
		}
		return "", nil
	}
	if !isPrivilegedUser() {
		return "running without root, SSH sessions are limited to the current user", nil
	}
	return "", nil
}

type directShellBackend struct{}

func (b *directShellBackend) OpenSession(request shellRequest) (shellSession, error) {
	shell := request.User.Shell
	var args []string
	if request.Command != "" {
		args = []string{shell, "-c", request.Command}
	} else {
		args = []string{"-" + filepath.Base(shell)}
	}
	if request.Term != "" {
		return OpenPtyShell(shell, args, request.Env, request.User.HomeDir, request.User.Uid, request.User.Gid, request.User.Groups, request.Rows, request.Cols, request.WidthPixels, request.HeightPixels)
	}
	return OpenSocketpairShell(shell, args, request.Env, request.User.HomeDir, request.User.Uid, request.User.Gid, request.User.Groups)
}

func (b *directShellBackend) Close() error {
	return nil
}

func lookupSFTPServer(_ adapter.PlatformInterface) (string, error) {
	for _, path := range []string{
		"/usr/libexec/sftp-server",
		"/usr/lib/openssh/sftp-server",
		"/usr/lib/ssh/sftp-server",
		"/usr/libexec/openssh/sftp-server",
	} {
		_, err := os.Stat(path)
		if err == nil {
			return path, nil
		}
	}
	return "", E.New("sftp-server not found")
}
