package persona

import "errors"

// Sentinel errors for persona validation.
var (
	// ErrNilCharacter is returned when a nil character is passed to validation.
	ErrNilCharacter = errors.New("character is nil")

	// ErrNilDNA is returned when character DNA is nil.
	ErrNilDNA = errors.New("character DNA is nil")

	// ErrInvalidAge is returned when age is out of valid range.
	ErrInvalidAge = errors.New("age must be between 0 and 150")

	// ErrMissingField is returned when a required field is missing.
	ErrMissingField = errors.New("required field is missing")

	// ErrInvalidSpecies is returned when an unknown species is provided.
	ErrInvalidSpecies = errors.New("invalid species type")

	// ErrInvalidEthnicity is returned when an unknown ethnicity is provided.
	ErrInvalidEthnicity = errors.New("invalid ethnicity code")

	// ErrInvalidGender is returned when an unknown gender is provided.
	ErrInvalidGender = errors.New("invalid gender identity")

	// ErrMorphLevelRequired is returned when morphology features require MorphLevel >= 25.
	ErrMorphLevelRequired = errors.New("morphology features require MorphLevel >= 25")

	// ErrImplausibleFeature is returned when a feature is biologically implausible.
	ErrImplausibleFeature = errors.New("feature is implausible for ethnicity")

	// ErrInconsistentAttributes is returned when attributes contradict each other.
	ErrInconsistentAttributes = errors.New("attributes are inconsistent with each other")

	// ErrInvalidFeatureType is returned when a morphology feature type is not recognized.
	ErrInvalidFeatureType = errors.New("invalid feature type")

	// ErrInvalidPoolConfig is returned when pool configuration is invalid.
	ErrInvalidPoolConfig = errors.New("invalid pool configuration")
)

// ValidationError wraps a validation error with field context.
type ValidationError struct {
	Field   string
	Value   interface{}
	Message string
	Err     error
}

// Error implements the error interface.
func (e *ValidationError) Error() string {
	if e.Field != "" {
		return e.Field + ": " + e.Message
	}
	return e.Message
}

// Unwrap returns the underlying error.
func (e *ValidationError) Unwrap() error {
	return e.Err
}

// ValidationErrors is a collection of validation errors.
type ValidationErrors []ValidationError

// Error implements the error interface.
func (e ValidationErrors) Error() string {
	if len(e) == 0 {
		return "no validation errors"
	}
	if len(e) == 1 {
		return e[0].Error()
	}
	msg := e[0].Error()
	for i := 1; i < len(e); i++ {
		msg += "; " + e[i].Error()
	}
	return msg
}

// HasErrors returns true if there are any validation errors.
func (e ValidationErrors) HasErrors() bool {
	return len(e) > 0
}

// Add appends a validation error.
func (e *ValidationErrors) Add(field, message string, err error) {
	*e = append(*e, ValidationError{
		Field:   field,
		Message: message,
		Err:     err,
	})
}

// AddValue appends a validation error with a value.
func (e *ValidationErrors) AddValue(field string, value interface{}, message string, err error) {
	*e = append(*e, ValidationError{
		Field:   field,
		Value:   value,
		Message: message,
		Err:     err,
	})
}
