package logging

import (
	"regexp"
	"strings"
)

// RedactedValue is the replacement string for sensitive data.
const RedactedValue = "[REDACTED]"

// sensitiveFieldPatterns are field name patterns that indicate sensitive data.
// These are matched case-insensitively.
var sensitiveFieldPatterns = []string{
	"password",
	"passwd",
	"secret",
	"token",
	"api_key",
	"apikey",
	"api-key",
	"auth",
	"bearer",
	"credential",
	"private",
	"key",
	"cert",
	"certificate",
}

// sensitiveValuePatterns are regex patterns to detect sensitive values.
var sensitiveValuePatterns = []*regexp.Regexp{
	// Bearer tokens
	regexp.MustCompile(`(?i)bearer\s+[a-zA-Z0-9\-_.~+/]+=*`),
	// API keys (common formats)
	regexp.MustCompile(`(?i)(?:api[_-]?key|token|secret)[=:]\s*["']?[a-zA-Z0-9\-_.~+/]{16,}["']?`),
	// AWS access keys
	regexp.MustCompile(`AKIA[0-9A-Z]{16}`),
	// Private keys
	regexp.MustCompile(`-----BEGIN [A-Z]+ PRIVATE KEY-----`),
	// Connection strings with passwords (supports empty username like redis://:pass@host)
	regexp.MustCompile(`(?i)(?:postgres|mysql|mongodb|redis)://[^:]*:[^@]+@`),
	// JWT tokens (three base64 parts separated by dots)
	regexp.MustCompile(`eyJ[a-zA-Z0-9\-_]+\.eyJ[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+`),
}

// exactSensitiveFields are field names that are always sensitive.
var exactSensitiveFields = map[string]bool{
	"password":          true,
	"passwd":            true,
	"secret":            true,
	"token":             true,
	"api_key":           true,
	"apikey":            true,
	"api-key":           true,
	"bearer":            true,
	"authorization":     true,
	"auth_token":        true,
	"access_token":      true,
	"refresh_token":     true,
	"private_key":       true,
	"secret_key":        true,
	"encryption_key":    true,
	"signing_key":       true,
	"client_secret":     true,
	"cookie":            true,
	"session":           true,
	"session_id":        true,
	"x-api-key":         true,
	"x-auth-token":      true,
	"credentials":       true,
	"credit_card":       true,
	"cc_number":         true,
	"cvv":               true,
	"ssn":               true,
	"social_security":   true,
	"bank_account":      true,
	"routing_number":    true,
	"cloudflare_token":  true,
	"gitea_token":       true,
	"woodpecker_secret": true,
}

// IsSensitiveField checks if a field name indicates sensitive data.
func IsSensitiveField(fieldName string) bool {
	lower := strings.ToLower(fieldName)

	// Check exact matches first (fast path)
	if exactSensitiveFields[lower] {
		return true
	}

	// Check pattern matches
	for _, pattern := range sensitiveFieldPatterns {
		if strings.Contains(lower, pattern) {
			return true
		}
	}

	return false
}

// RedactValue redacts a value if it matches sensitive patterns.
func RedactValue(value string) string {
	for _, pattern := range sensitiveValuePatterns {
		if pattern.MatchString(value) {
			return RedactedValue
		}
	}
	return value
}

// ContainsSensitiveData checks if a string contains sensitive data patterns.
func ContainsSensitiveData(value string) bool {
	for _, pattern := range sensitiveValuePatterns {
		if pattern.MatchString(value) {
			return true
		}
	}
	return false
}
