package auth

import (
	"regexp"
	"strings"

	apperrors "github.com/nexuscrm/backend/pkg/errors"
	"golang.org/x/crypto/bcrypt"
)

// HashPassword hashes a password using bcrypt
func HashPassword(password string) (string, error) {
	bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	return string(bytes), err
}

// VerifyPassword compares a plain password with a hashed password
func VerifyPassword(password, hash string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
	return err == nil
}

// ValidateBcryptCost checks that a bcrypt hash meets the minimum cost factor.
// Returns an error if the cost is below bcrypt.DefaultCost.
func ValidateBcryptCost(hash string) error {
	cost, err := bcrypt.Cost([]byte(hash))
	if err != nil {
		return apperrors.NewValidationError("password", "malformed bcrypt hash")
	}
	if cost < bcrypt.DefaultCost {
		return apperrors.NewValidationError("password", "pre-computed password hash has insufficient bcrypt cost factor")
	}
	return nil
}

// ValidatePasswordStrength checks if a password meets security requirements
func ValidatePasswordStrength(password string) error {
	if len(password) < 8 {
		return apperrors.NewValidationError("password", "must be at least 8 characters long")
	}

	if len(password) > 128 {
		return apperrors.NewValidationError("password", "must not exceed 128 characters")
	}

	// Check for at least one uppercase letter
	if !regexp.MustCompile(`[A-Z]`).MatchString(password) {
		return apperrors.NewValidationError("password", "must contain at least one uppercase letter")
	}

	// Check for at least one lowercase letter
	if !regexp.MustCompile(`[a-z]`).MatchString(password) {
		return apperrors.NewValidationError("password", "must contain at least one lowercase letter")
	}

	// Check for at least one digit
	if !regexp.MustCompile(`[0-9]`).MatchString(password) {
		return apperrors.NewValidationError("password", "must contain at least one number")
	}

	// Check for at least one special character
	if !regexp.MustCompile(`[@$!%*?&]`).MatchString(password) {
		return apperrors.NewValidationError("password", "must contain at least one special character (@$!%*?&)")
	}

	return nil
}

// IsValidEmail validates an email address format
func IsValidEmail(email string) bool {
	email = strings.TrimSpace(email)
	if len(email) < 3 || len(email) > 254 {
		return false
	}

	emailRegex := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
	return emailRegex.MatchString(email)
}
