package controllers

import (
	"fmt"
	"regexp"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
)

// ValidationHelper provides validation utilities
type ValidationHelper struct {
	validator *validator.Validate
}

// ValidationError represents a validation error
type ValidationError struct {
	Field   string `json:"field"`
	Message string `json:"message"`
	Tag     string `json:"tag"`
}

// NewValidationHelper creates a new ValidationHelper instance
func NewValidationHelper() *ValidationHelper {
	v := validator.New()
	
	// Register custom validators
	_ = v.RegisterValidation("slug", validateSlug)
	_ = v.RegisterValidation("color", validateColor)
	
	return &ValidationHelper{
		validator: v,
	}
}

// Validate validates a struct and returns user-friendly errors
func (vh *ValidationHelper) Validate(data interface{}) []ValidationError {
	err := vh.validator.Struct(data)
	if err == nil {
		return nil
	}

	var validationErrors []ValidationError
	for _, err := range err.(validator.ValidationErrors) {
		validationErrors = append(validationErrors, ValidationError{
			Field:   strings.ToLower(err.Field()),
			Message: vh.getErrorMessage(err),
			Tag:     err.Tag(),
		})
	}

	return validationErrors
}

// ValidateAndRespond validates data and sends error response if invalid
// Returns true if valid, false if invalid (and response already sent)
func (vh *ValidationHelper) ValidateAndRespond(c *gin.Context, data interface{}) bool {
	errors := vh.Validate(data)
	if len(errors) > 0 {
		Respond.ValidationError(c, errors)
		return false
	}
	return true
}

// getErrorMessage returns a user-friendly error message for a validation error
func (vh *ValidationHelper) getErrorMessage(err validator.FieldError) string {
	field := err.Field()
	
	switch err.Tag() {
	case "required":
		return fmt.Sprintf("%s is required", field)
	case "email":
		return fmt.Sprintf("%s must be a valid email address", field)
	case "min":
		return fmt.Sprintf("%s must be at least %s characters", field, err.Param())
	case "max":
		return fmt.Sprintf("%s must be at most %s characters", field, err.Param())
	case "len":
		return fmt.Sprintf("%s must be exactly %s characters", field, err.Param())
	case "url":
		return fmt.Sprintf("%s must be a valid URL", field)
	case "slug":
		return fmt.Sprintf("%s must be a valid slug (lowercase, alphanumeric, hyphens)", field)
	case "color":
		return fmt.Sprintf("%s must be a valid hex color code", field)
	case "oneof":
		return fmt.Sprintf("%s must be one of: %s", field, err.Param())
	case "gte":
		return fmt.Sprintf("%s must be greater than or equal to %s", field, err.Param())
	case "lte":
		return fmt.Sprintf("%s must be less than or equal to %s", field, err.Param())
	case "gt":
		return fmt.Sprintf("%s must be greater than %s", field, err.Param())
	case "lt":
		return fmt.Sprintf("%s must be less than %s", field, err.Param())
	default:
		return fmt.Sprintf("%s is invalid", field)
	}
}

// IsValidEmail checks if a string is a valid email
func (vh *ValidationHelper) IsValidEmail(email string) bool {
	return vh.validator.Var(email, "required,email") == nil
}

// IsValidURL checks if a string is a valid URL
func (vh *ValidationHelper) IsValidURL(url string) bool {
	return vh.validator.Var(url, "required,url") == nil
}

// IsValidSlug checks if a string is a valid slug
func (vh *ValidationHelper) IsValidSlug(slug string) bool {
	return vh.validator.Var(slug, "required,slug") == nil
}

// SanitizeString removes leading/trailing whitespace and normalizes spaces
func (vh *ValidationHelper) SanitizeString(s string) string {
	// Trim whitespace
	s = strings.TrimSpace(s)
	// Replace multiple spaces with single space
	s = regexp.MustCompile(`\s+`).ReplaceAllString(s, " ")
	return s
}

// SanitizeEmail normalizes an email address
func (vh *ValidationHelper) SanitizeEmail(email string) string {
	return strings.ToLower(strings.TrimSpace(email))
}

// SanitizeSlug normalizes a slug
func (vh *ValidationHelper) SanitizeSlug(slug string) string {
	slug = strings.ToLower(strings.TrimSpace(slug))
	// Replace spaces with hyphens
	slug = regexp.MustCompile(`\s+`).ReplaceAllString(slug, "-")
	// Remove non-alphanumeric characters except hyphens
	slug = regexp.MustCompile(`[^a-z0-9-]`).ReplaceAllString(slug, "")
	// Replace multiple hyphens with single hyphen
	slug = regexp.MustCompile(`-+`).ReplaceAllString(slug, "-")
	// Remove leading/trailing hyphens
	slug = strings.Trim(slug, "-")
	return slug
}

// Custom validator functions

// validateSlug validates that a string is a valid slug
func validateSlug(fl validator.FieldLevel) bool {
	slug := fl.Field().String()
	if slug == "" {
		return true // Let 'required' handle empty values
	}
	// Valid slug: lowercase alphanumeric and hyphens, no leading/trailing hyphens
	matched, _ := regexp.MatchString(`^[a-z0-9]+(-[a-z0-9]+)*$`, slug)
	return matched
}

// validateColor validates that a string is a valid hex color code
func validateColor(fl validator.FieldLevel) bool {
	color := fl.Field().String()
	if color == "" {
		return true // Let 'required' handle empty values
	}
	// Valid color: #RGB, #RRGGBB, #RGBA, #RRGGBBAA
	matched, _ := regexp.MatchString(`^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{8})$`, color)
	return matched
}

// Global ValidationHelper instance for convenience
var Validator = NewValidationHelper()
