package com.airlock.iam.flow.shared.domain.model.userdata;

import com.airlock.iam.base.api.domain.model.validation.GenericError;
import com.airlock.iam.base.api.domain.model.validation.ValidationResult;
import com.airlock.iam.base.api.domain.model.validation.ValidatorError;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.List;
import java.util.Optional;
import lombok.NonNull;

public record IdentificationByUserDataFailure(
   @NonNull IdentificationByUserDataFailure.IdentificationByUserDataError error, @NonNull Optional<ValidationResult> validationResult
) {
   @SuppressFBWarnings(justification = "generated code")
   public IdentificationByUserDataFailure {
      if (error == null) {
         throw new NullPointerException("error is marked non-null but is null");
      }

      if (validationResult == null) {
         throw new NullPointerException("validationResult is marked non-null but is null");
      }
   }

   public boolean hasError(IdentificationByUserDataFailure.IdentificationByUserDataError expectedError) {
      return this.error().equals(expectedError);
   }

   public static IdentificationByUserDataFailure userDataInvalid(ValidationResult validationResult) {
      return new IdentificationByUserDataFailure(IdentificationByUserDataFailure.IdentificationByUserDataError.USER_DATA_INVALID, Optional.of(validationResult));
   }

   public static IdentificationByUserDataFailure userDataMissing(List<String> contextDataItemNames) {
      List<ValidatorError> validatorErrors = contextDataItemNames.stream().map(name -> ValidatorError.validatorError(name, GenericError.REQUIRED)).toList();
      if (contextDataItemNames.isEmpty()) {
         validatorErrors = List.of(ValidatorError.validatorError(GenericError.INVALID_VALUE));
      }

      return new IdentificationByUserDataFailure(
         IdentificationByUserDataFailure.IdentificationByUserDataError.USER_DATA_MISSING, Optional.of(ValidationResult.invalid(validatorErrors))
      );
   }

   public static IdentificationByUserDataFailure userDataNotUnique() {
      return new IdentificationByUserDataFailure(IdentificationByUserDataFailure.IdentificationByUserDataError.USER_DATA_NOT_UNIQUE, Optional.empty());
   }

   public static IdentificationByUserDataFailure userDataNotFound() {
      return new IdentificationByUserDataFailure(IdentificationByUserDataFailure.IdentificationByUserDataError.USER_DATA_NOT_FOUND, Optional.empty());
   }

   public enum IdentificationByUserDataError {
      USER_DATA_INVALID,
      USER_DATA_NOT_UNIQUE,
      USER_DATA_MISSING,
      USER_DATA_NOT_FOUND;
   }
}
