package utils

import (
	"fmt"
	"slices"
	"strings"

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

// ValidSSHKeyTypes is a list of valid SSH key types
//
// Please make sure that all the types in this list are supported by dropbear
// https://github.com/mkj/dropbear/blob/003c5fcaabc114430d5d14142e95ffdbbd2d19b6/src/signkey.c#L37
//
// ssh-dss is not allowed here as it's insecure
var ValidSSHKeyTypes = []string{
	ssh.KeyAlgoRSA,
	ssh.KeyAlgoED25519,
	ssh.KeyAlgoECDSA256,
	ssh.KeyAlgoECDSA384,
	ssh.KeyAlgoECDSA521,
	ssh.KeyAlgoSKED25519,
	ssh.KeyAlgoSKECDSA256,
}

// ValidateSSHKey validates authorized_keys file content
func ValidateSSHKey(sshKey string) error {
	// validate SSH key
	var (
		hasValidPublicKey = false
		lastError         = fmt.Errorf("no valid SSH key found")
	)
	for _, key := range strings.Split(sshKey, "\n") {
		key = strings.TrimSpace(key)

		// skip empty lines and comments
		if key == "" || strings.HasPrefix(key, "#") {
			continue
		}

		parsedPublicKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(key))
		if err != nil {
			lastError = err
			continue
		}

		if parsedPublicKey == nil {
			continue
		}

		parsedType := parsedPublicKey.Type()
		textType := strings.Fields(key)[0]

		if parsedType != textType {
			lastError = fmt.Errorf("parsed SSH key type %s does not match type in text %s", parsedType, textType)
			continue
		}

		if !slices.Contains(ValidSSHKeyTypes, parsedType) {
			lastError = fmt.Errorf("invalid SSH key type: %s", parsedType)
			continue
		}

		hasValidPublicKey = true
	}

	if !hasValidPublicKey {
		return lastError
	}

	return nil
}
