package logging

import (
	"regexp"
	"strings"
)

// Patterns for sensitive data
var (
	// API keys: 32+ hex characters
	apiKeyPattern = regexp.MustCompile(`\b[0-9a-fA-F]{32,}\b`)

	// JWT tokens
	jwtPattern = regexp.MustCompile(`eyJ[a-zA-Z0-9_-]{10,}\.eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}`)

	// Password-like fields in logs
	passwordPattern = regexp.MustCompile(
		`(?i)(password|passwd|pwd|secret|token|key)["']?\s*[:=]\s*["']?` +
			`([^"'\s,}]+)`,
	)

	// Redis URLs with passwords
	redisPasswordPattern = regexp.MustCompile(`redis://:[^@]+@`)

	// Database connection strings - PostgreSQL
	postgresPasswordPattern = regexp.MustCompile(`(postgresql?://[^:]+:)[^@]+(@)`)

	// Generic connection strings with passwords
	connStringPasswordPattern = regexp.MustCompile(`(password[=:])[^\s&;]+`)

	// HTTP Authorization headers
	authHeaderPattern = regexp.MustCompile(`(Authorization:\s*(?:Bearer|Basic)\s+)[^\s]+`)

	// Private keys
	privateKeyPattern = regexp.MustCompile(`(-----BEGIN (?:RSA|EC|DSA|OPENSSH) PRIVATE KEY-----)[\s\S]*?(-----END (?:RSA|EC|DSA|OPENSSH) PRIVATE KEY-----)`)
)

// SanitizeLogMessage removes sensitive data from log messages
func SanitizeLogMessage(message string) string {
	// Redact API keys
	message = apiKeyPattern.ReplaceAllString(message, "[REDACTED-API-KEY]")

	// Redact JWT tokens
	message = jwtPattern.ReplaceAllString(message, "[REDACTED-JWT]")

	// Redact password-like fields
	message = passwordPattern.ReplaceAllStringFunc(message, func(match string) string {
		parts := passwordPattern.FindStringSubmatch(match)
		if len(parts) >= 2 {
			return parts[1] + "=[REDACTED]"
		}
		return match
	})

	// Redact Redis passwords from URLs
	message = redisPasswordPattern.ReplaceAllString(message, "redis://:[REDACTED]@")

	// Redact PostgreSQL connection strings
	message = postgresPasswordPattern.ReplaceAllString(message, "${1}[REDACTED]${2}")

	// Redact generic connection string passwords
	message = connStringPasswordPattern.ReplaceAllString(message, "${1}[REDACTED]")

	// Redact HTTP Authorization headers
	message = authHeaderPattern.ReplaceAllString(message, "${1}[REDACTED]")

	// Redact private keys
	message = privateKeyPattern.ReplaceAllString(message, "[REDACTED-PRIVATE-KEY]")

	return message
}

// SanitizeArgs removes sensitive data from structured log arguments
func SanitizeArgs(args []any) []any {
	sanitized := make([]any, len(args))
	copy(sanitized, args)

	for i := 0; i < len(sanitized)-1; i += 2 {
		// Check if this is a key-value pair
		key, okKey := sanitized[i].(string)
		value, okValue := sanitized[i+1].(string)

		if okKey && okValue {
			lowerKey := strings.ToLower(key)
			// Redact sensitive fields
			if strings.Contains(lowerKey, "password") ||
				strings.Contains(lowerKey, "secret") ||
				strings.Contains(lowerKey, "token") ||
				strings.Contains(lowerKey, "key") ||
				strings.Contains(lowerKey, "api") {
				sanitized[i+1] = "[REDACTED]"
			} else if strings.HasPrefix(value, "redis://") {
				sanitized[i+1] = SanitizeLogMessage(value)
			}
		}
	}

	return sanitized
}

// RedactAPIKey masks an API key for logging (shows first/last 4 chars)
func RedactAPIKey(key string) string {
	if len(key) <= 8 {
		return "[REDACTED]"
	}
	return key[:4] + "..." + key[len(key)-4:]
}
