package com.airlock.iam.base.api.domain.model.validation;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

final class ValidationResultImpl implements ValidationResult {
   private List<ValidatorError> errors;
   private boolean valid;

   static ValidationResultImpl valid() {
      return builder().valid(true).errors(Collections.emptyList()).build();
   }

   static ValidationResultImpl invalidResult(ValidatorError error) {
      return builder().valid(false).error(error).build();
   }

   static ValidationResultImpl invalidResult(List<ValidatorError> errors) {
      if (errors.isEmpty()) {
         throw new IllegalArgumentException("errors must not be empty for invalid result");
      } else {
         return builder().valid(false).errors(errors).build();
      }
   }

   static ValidationResultImpl invalidResult() {
      return builder().valid(false).errors(Collections.emptyList()).build();
   }

   @Override
   public boolean isValid() {
      return this.valid;
   }

   @Override
   public String getFailure() {
      return this.valid ? "" : this.errors.stream().map(ValidatorError::getMessage).collect(Collectors.joining(", "));
   }

   @Override
   public <T extends ValidationResultType> boolean contains(T validationResultType) {
      return this.valid ? false : this.errors.stream().anyMatch(r -> r.getType().equals(validationResultType));
   }

   @Override
   public String toString() {
      return this.valid ? "VALID" : "INVALID: " + this.getFailure();
   }

   @Override
   public List<ValidatorError> getErrors() {
      return this.errors;
   }

   @Override
   public ValidationResult mergeWith(ValidationResult validation) {
      this.valid = this.isValid() && validation.isValid();
      this.errors = Stream.concat(this.errors.stream(), validation.getErrors().stream()).collect(Collectors.toList());
      return this;
   }

   @Override
   public boolean hasError(String field, ValidationResultType type) {
      return this.isValid() ? false : this.getErrors().stream().anyMatch(error -> field.equals(error.getField()) && type.equals(error.getType()));
   }

   @SuppressFBWarnings(justification = "generated code")
   ValidationResultImpl(List<ValidatorError> errors, boolean valid) {
      this.errors = errors;
      this.valid = valid;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static ValidationResultImpl.ValidationResultImplBuilder builder() {
      return new ValidationResultImpl.ValidationResultImplBuilder();
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public boolean equals(Object o) {
      if (o == this) {
         return true;
      } else if (!(o instanceof ValidationResultImpl other)) {
         return false;
      } else {
         if (this.valid != other.valid) {
            return false;
         }

         Object this$errors = this.errors;
         Object other$errors = other.errors;
         return this$errors == null ? other$errors == null : this$errors.equals(other$errors);
      }
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public int hashCode() {
      int PRIME = 59;
      int result = 1;
      result = result * 59 + (this.valid ? 79 : 97);
      Object $errors = this.errors;
      return result * 59 + ($errors == null ? 43 : $errors.hashCode());
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class ValidationResultImplBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<ValidatorError> errors;
      @SuppressFBWarnings(justification = "generated code")
      private boolean valid;

      @SuppressFBWarnings(justification = "generated code")
      ValidationResultImplBuilder() {
      }

      @SuppressFBWarnings(justification = "generated code")
      public ValidationResultImpl.ValidationResultImplBuilder error(ValidatorError error) {
         if (this.errors == null) {
            this.errors = new ArrayList<>();
         }

         this.errors.add(error);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public ValidationResultImpl.ValidationResultImplBuilder errors(Collection<? extends ValidatorError> errors) {
         if (errors == null) {
            throw new NullPointerException("errors cannot be null");
         }

         if (this.errors == null) {
            this.errors = new ArrayList<>();
         }

         this.errors.addAll(errors);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public ValidationResultImpl.ValidationResultImplBuilder clearErrors() {
         if (this.errors != null) {
            this.errors.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public ValidationResultImpl.ValidationResultImplBuilder valid(boolean valid) {
         this.valid = valid;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public ValidationResultImpl build() {
         return new ValidationResultImpl(switch (this.errors == null ? 0 : this.errors.size()) {
            case 0 -> Collections.emptyList();
            case 1 -> Collections.singletonList(this.errors.get(0));
            default -> Collections.unmodifiableList(new ArrayList<>(this.errors));
         }, this.valid);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "ValidationResultImpl.ValidationResultImplBuilder(errors=" + this.errors + ", valid=" + this.valid + ")";
      }
   }
}
