package vault

import (
	"regexp"
	"strings"
)

// SecretType represents the semantic type of a secret entry.
type SecretType string

const (
	SecretTypeAPIKey      SecretType = "api_key"
	SecretTypeBearerToken SecretType = "bearer_token"
	SecretTypeBasicAuth   SecretType = "basic_auth"
	SecretTypeSSHKey      SecretType = "ssh_key"
	SecretTypePassword    SecretType = "password"
	SecretTypeCertificate SecretType = "certificate"
	SecretTypeDatabaseURL SecretType = "database_url"
	SecretTypeTOTPSeed    SecretType = "totp_seed"
	SecretTypeCustom      SecretType = "custom"
)

// AllSecretTypes returns all valid secret types.
func AllSecretTypes() []SecretType {
	return []SecretType{
		SecretTypeAPIKey,
		SecretTypeBearerToken,
		SecretTypeBasicAuth,
		SecretTypeSSHKey,
		SecretTypePassword,
		SecretTypeCertificate,
		SecretTypeDatabaseURL,
		SecretTypeTOTPSeed,
		SecretTypeCustom,
	}
}

// SecretTypeFromString parses a secret type from string, defaulting to custom.
func SecretTypeFromString(s string) SecretType {
	switch strings.ToLower(s) {
	case "api_key":
		return SecretTypeAPIKey
	case "bearer_token":
		return SecretTypeBearerToken
	case "basic_auth":
		return SecretTypeBasicAuth
	case "ssh_key":
		return SecretTypeSSHKey
	case string(SecretTypePassword):
		return SecretTypePassword
	case "certificate":
		return SecretTypeCertificate
	case "database_url":
		return SecretTypeDatabaseURL
	case "totp_seed":
		return SecretTypeTOTPSeed
	case "custom":
		return SecretTypeCustom
	default:
		return SecretTypeCustom
	}
}

// IsValidSecretType checks if the given string is a valid secret type.
func IsValidSecretType(s string) bool {
	switch strings.ToLower(s) {
	case "api_key", "bearer_token", "basic_auth", "ssh_key",
		string(SecretTypePassword), "certificate", "database_url", "totp_seed", "custom":
		return true
	}
	return false
}

// detection patterns for common secret types
var (
	awsAccessKeyPattern      = regexp.MustCompile(`^AKIA[0-9A-Z]{16}$`)
	githubPATPattern         = regexp.MustCompile(`^ghp_[a-zA-Z0-9]{36}$`)
	githubFineGrainedPattern = regexp.MustCompile(`^github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}$`)
	githubOAuthPattern       = regexp.MustCompile(`^gho_[a-zA-Z0-9]{36}$`)
	githubAppPattern         = regexp.MustCompile(`^ghs_[a-zA-Z0-9]{36}$`)
	githubRefreshPattern     = regexp.MustCompile(`^ghr_[a-zA-Z0-9]{36}$`)
	sshRSAPattern            = regexp.MustCompile(`(?i)^-----BEGIN RSA PRIVATE KEY-----`)
	sshECDSAPattern          = regexp.MustCompile(`(?i)^-----BEGIN EC PRIVATE KEY-----`)
	sshED25519Pattern        = regexp.MustCompile(`(?i)^-----BEGIN OPENSSH PRIVATE KEY-----`)
	sshDSAPattern            = regexp.MustCompile(`(?i)^-----BEGIN DSA PRIVATE KEY-----`)
	databaseURLPattern       = regexp.MustCompile(`^(postgres(ql)?|mysql|mongodb(\+srv)?|redis|sqlite|mariadb)://`)
	basicAuthPattern         = regexp.MustCompile(`^[^:]+:[^:]+$`)
	genericAPIKeyPattern     = regexp.MustCompile(`^[a-zA-Z0-9_-]{32,}$`)
	bearerTokenPattern       = regexp.MustCompile(`^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+$`)
	totpSeedPattern          = regexp.MustCompile(`^[A-Z2-7]{16,}$`)
	certPattern              = regexp.MustCompile(`(?i)^-----BEGIN CERTIFICATE-----`)
)

// DetectSecretType attempts to automatically detect the secret type from its value.
// Returns the most specific matching type, or SecretTypePassword as a fallback.
//
//nolint:gocyclo // complexity inherent to pattern matching against many secret type signatures
func DetectSecretType(value string) SecretType {
	value = strings.TrimSpace(value)
	if value == "" {
		return SecretTypePassword
	}

	// Check for SSH keys first (most specific)
	if sshRSAPattern.MatchString(value) || sshECDSAPattern.MatchString(value) ||
		sshED25519Pattern.MatchString(value) || sshDSAPattern.MatchString(value) {
		return SecretTypeSSHKey
	}

	// Check for certificates
	if certPattern.MatchString(value) {
		return SecretTypeCertificate
	}

	// Check for database URLs
	if databaseURLPattern.MatchString(value) {
		return SecretTypeDatabaseURL
	}

	// Check for GitHub tokens
	if githubPATPattern.MatchString(value) || githubFineGrainedPattern.MatchString(value) ||
		githubOAuthPattern.MatchString(value) || githubAppPattern.MatchString(value) ||
		githubRefreshPattern.MatchString(value) {
		return SecretTypeBearerToken
	}

	// Check for AWS keys
	if awsAccessKeyPattern.MatchString(value) {
		return SecretTypeAPIKey
	}

	// Check for TOTP seeds (base32 encoded)
	if totpSeedPattern.MatchString(value) && len(value) >= 16 {
		return SecretTypeTOTPSeed
	}

	// Check for JWT/bearer tokens
	if bearerTokenPattern.MatchString(value) {
		return SecretTypeBearerToken
	}

	// Check for basic auth format
	if basicAuthPattern.MatchString(value) && strings.Contains(value, ":") {
		// Make sure it's not just a URL or something else
		parts := strings.SplitN(value, ":", 2)
		if len(parts) == 2 && len(parts[0]) > 0 && len(parts[1]) > 0 {
			return SecretTypeBasicAuth
		}
	}

	// Check for generic API keys (long alphanumeric strings)
	if genericAPIKeyPattern.MatchString(value) && len(value) >= 32 {
		return SecretTypeAPIKey
	}

	// Default to password for anything else
	return SecretTypePassword
}

// UsageHintForType returns a predefined usage hint for the given secret type.
func UsageHintForType(t SecretType) string {
	switch t {
	case SecretTypeAPIKey:
		return "Set as header or query parameter depending on API documentation. Common: X-API-Key: <key> or ?api_key=<key>"
	case SecretTypeBearerToken:
		return "Set Header Authorization: Bearer <token>"
	case SecretTypeBasicAuth:
		return "Encode as base64(user:pass) and set Header Authorization: Basic <encoded>"
	case SecretTypeSSHKey:
		return "Write to temporary file with chmod 600 before use. Use with ssh -i <keyfile>"
	case SecretTypePassword:
		return "Use for authentication. Consider using a password manager or secret injection."
	case SecretTypeCertificate:
		return "Use with TLS/SSL configuration. May require private key pairing."
	case SecretTypeDatabaseURL:
		return "Use as connection string. Ensure credentials are not logged."
	case SecretTypeTOTPSeed:
		return "Use with TOTP generator. Never share the seed - only share generated codes."
	case SecretTypeCustom:
		return "Follow the specific integration instructions for this secret."
	default:
		return ""
	}
}

// SecretTypeIcon returns an icon/emoji for the given secret type.
func SecretTypeIcon(t SecretType) string {
	switch t {
	case SecretTypeAPIKey:
		return "🔑"
	case SecretTypeBearerToken:
		return "🎫"
	case SecretTypeBasicAuth:
		return "🔐"
	case SecretTypeSSHKey:
		return "🔒"
	case SecretTypePassword:
		return "🗝️"
	case SecretTypeCertificate:
		return "📜"
	case SecretTypeDatabaseURL:
		return "🗄️"
	case SecretTypeTOTPSeed:
		return "⏱️"
	case SecretTypeCustom:
		return "📦"
	default:
		return "❓"
	}
}
