package validate

import (
	"errors"
	"fmt"
	"strings"

	ut "github.com/go-playground/universal-translator"
	"github.com/go-playground/validator/v10"

	errs "gateway/internal/library/errors"
	"gateway/internal/library/errors/code"
)

// ValidationError holds information about a single validation error.
type ValidationError struct {
	Field   string `json:"field"`
	Message string `json:"message"`
}

// ValidationErrors is a slice of ValidationError that implements the error interface.
type ValidationErrors []ValidationError

func (ve ValidationErrors) Error() string {
	if len(ve) == 0 {
		return ""
	}
	var sb strings.Builder
	sb.WriteString("validation failed:")
	for i, e := range ve {
		fmt.Fprintf(&sb, " field='%s', message='%s'", e.Field, e.Message)
		if i < len(ve)-1 {
			sb.WriteString(";")
		}
	}
	return sb.String()
}

// Is supports errors.Is when comparing against ValidationErrors.
func (ValidationErrors) Is(target error) bool {
	_, ok := target.(ValidationErrors)
	return ok
}

// AsErrors unwraps err into ValidationErrors when present.
func AsErrors(err error) (ValidationErrors, bool) {
	var ve ValidationErrors
	if errors.As(err, &ve) {
		return ve, true
	}
	return nil, false
}

// ToBusinessError maps field validation failures to InputInvalidFormat (HTTP 400).
func (ve ValidationErrors) ToBusinessError(scope code.Scope) *errs.Error {
	return errs.For(scope).InputInvalidFormat(ve.Error())
}

// translateValidationErrors converts validator.ValidationErrors to our custom ValidationErrors.
func translateValidationErrors(valErrs validator.ValidationErrors, trans ut.Translator) ValidationErrors {
	customErrors := make(ValidationErrors, 0, len(valErrs))
	for _, err := range valErrs {
		customErrors = append(customErrors, ValidationError{
			Field:   err.Field(), // Already transformed by RegisterTagNameFunc
			Message: err.Translate(trans),
		})
	}
	return customErrors
}
