// Package validation provides shared input validation utilities.
package validation

import (
	"net"
	"net/mail"
	"strings"
)

// ValidateEmail validates an email address using Go's standard mail package.
// Returns an error message if the email is invalid, or an empty string if valid.
// This provides consistent email validation across all services.
func ValidateEmail(email string) string {
	email = strings.TrimSpace(email)
	if email == "" {
		return "Email address is required"
	}

	// Use Go's mail package for proper RFC 5322 email validation
	if _, err := mail.ParseAddress(email); err != nil {
		return "Please enter a valid email address"
	}

	return ""
}

// IsValidEmail returns true if the email is valid, false otherwise.
// This is a convenience wrapper around ValidateEmail for simple boolean checks.
func IsValidEmail(email string) bool {
	return ValidateEmail(email) == ""
}

// MaskEmail masks an email address for safe logging.
// Example: "john.doe@example.com" becomes "jo***@example.com"
// This prevents PII exposure in logs while still allowing identification.
func MaskEmail(email string) string {
	email = strings.TrimSpace(email)
	if email == "" {
		return "***"
	}

	parts := strings.Split(email, "@")
	if len(parts) != 2 {
		return "***"
	}

	localPart := parts[0]
	domain := parts[1]

	// Mask local part based on length
	var maskedLocal string
	switch {
	case len(localPart) <= 1:
		maskedLocal = "*"
	case len(localPart) <= 3:
		maskedLocal = localPart[:1] + "***"
	default:
		maskedLocal = localPart[:2] + "***"
	}

	return maskedLocal + "@" + domain
}

// MaskIP masks an IP address for safe logging.
// IPv4 example: "192.168.1.100" becomes "192.168.1.***"
// IPv6 example: "2001:db8::1" becomes "2001:db8::***"
// This prevents PII exposure in logs while still allowing network identification.
func MaskIP(ip string) string {
	ip = strings.TrimSpace(ip)
	if ip == "" {
		return "***"
	}

	// Remove port if present (format: "IP:port" or "[IPv6]:port")
	host, _, err := net.SplitHostPort(ip)
	if err == nil {
		ip = host
	}

	// Parse to determine if IPv4 or IPv6
	parsedIP := net.ParseIP(ip)
	if parsedIP == nil {
		return "***"
	}

	// Check if IPv4
	if ipv4 := parsedIP.To4(); ipv4 != nil {
		// Mask last octet: 192.168.1.100 -> 192.168.1.***
		parts := strings.Split(ip, ".")
		if len(parts) == 4 {
			return parts[0] + "." + parts[1] + "." + parts[2] + ".***"
		}
		return "***"
	}

	// IPv6: mask last segment
	// Example: 2001:db8:85a3::8a2e:370:7334 -> 2001:db8:85a3::8a2e:370:***
	parts := strings.Split(ip, ":")
	if len(parts) > 1 {
		parts[len(parts)-1] = "***"
		return strings.Join(parts, ":")
	}

	return "***"
}
