package io.fluxcapacitor.javaclient.tracking.handling.validation;

import io.fluxcapacitor.javaclient.common.exception.FunctionalException;
import lombok.Getter;
import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl;

import javax.validation.ConstraintViolation;
import javax.validation.Path;
import java.beans.ConstructorProperties;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import static java.lang.System.lineSeparator;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toCollection;

@Getter
public class ValidationException extends FunctionalException {

    private final SortedSet<String> violations;

    public ValidationException(Set<? extends ConstraintViolation<?>> violations) {
        super(violations.stream().map(ValidationException::format).collect(Collectors.joining(lineSeparator())));
        this.violations = violations.stream().map(ValidationException::format).collect(toCollection(TreeSet::new));
    }

    @ConstructorProperties({"message", "violations"})
    public ValidationException(String message, Set<String> violations) {
        super(message);
        this.violations = new TreeSet<>(violations);
    }

    @SuppressWarnings("unchecked")
    protected static String format(ConstraintViolation<?> v) {
        //If the validator uses a custom message we just return the message, otherwise we add the property path
        try {
            ConstraintDescriptorImpl constraintDescriptor = (ConstraintDescriptorImpl) v.getConstraintDescriptor();
            Method method = constraintDescriptor.getAnnotationType().getDeclaredMethod("message");
            Object defaultMessage = method.getDefaultValue();
            if (!Objects.equals(defaultMessage, v.getMessage())) {
                return v.getMessage();
            }
        } catch (Exception ignored) {
        }
        return String.format("%s %s", StreamSupport.stream(v.getPropertyPath().spliterator(), false)
                .reduce((a, b) -> b).map(Path.Node::getName).orElse(v.getPropertyPath().toString()), v.getMessage());
    }

    protected static String format(Set<? extends ConstraintViolation<?>> violations) {
        return violations.stream().map(ValidationException::format).sorted().collect(joining(lineSeparator()));
    }
}

@@ -379,48 +379,30 @@
 ang.
-reflect.Method;%0Aimport java.util.Objects
+annotation.ElementType
 ;%0Aim
@@ -1361,43 +1361,8 @@
  %7D%0A%0A
-    @SuppressWarnings(%22unchecked%22)%0A
     
@@ -1432,560 +1432,145 @@
     
-//If the validator uses a custom message we just return the message, otherwise we add the property path%0A        try %7B%0A            ConstraintDescriptorImpl constraintDescriptor = (ConstraintDescriptorImpl) v.getConstraintDescriptor();%0A            Method method = constraintDescriptor.getAnnotationType().getDeclaredMethod(%22message%22);%0A            Object defaultMessage = method.getDefaultValue();%0A            if (!Objects.equals(defaultMessage, v.getMessage())) %7B%0A                return v.getMessage();%0A            %7D%0A        %7D catch (Exception ignored) %7B
+if (((ConstraintDescriptorImpl) v.getConstraintDescriptor()).getElementType() == ElementType.METHOD) %7B%0A            return v.getMessage();
 %0A   

Revert "Improve validation exception message"