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

import com.airlock.iam.authentication.api.domain.model.step.AuthenticationFlowStep;
import com.airlock.iam.base.api.domain.model.mapification.Mapifiable;
import com.airlock.iam.base.api.domain.model.mapification.MapifiedValues;
import com.airlock.iam.base.domain.model.mapification.MapificationUtils;
import com.airlock.iam.base.domain.model.mapification.MapifiedValuesBuilder;
import com.airlock.iam.common.api.domain.model.otp.UnverifiedOtp;
import com.airlock.iam.core.misc.authen.result.AuthenticationFailed;
import com.airlock.iam.core.misc.authen.result.MtanChoiceTokenMapificationUtil;
import com.airlock.iam.flow.api.domain.model.step.StepAction;
import com.airlock.iam.flow.api.domain.model.step.StepError;
import com.airlock.iam.flow.api.domain.model.step.StepResult;
import com.airlock.iam.flow.api.domain.model.step.StepResultData;
import com.airlock.iam.flow.api.domain.model.step.StepResultDataCollection;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Collection;
import java.util.List;
import lombok.NonNull;

public interface MtanOtpCheckingStep extends AuthenticationFlowStep {
   String RESEND_POSSIBLE_ATTRIBUTE = "resendPossible";
   String PHONE_NUMBER_ATTRIBUTE = "phoneNumber";

   StepResult checkOtp(UnverifiedOtp var1);

   StepResult getNumberChoice();

   StepResult selectMtanToken(String var1);

   StepResult resendOtp();

   StepResult resendOtpPossible();

   enum MtanAuthStepActions implements StepAction {
      MTAN_OTP_REQUIRED,
      MTAN_TOKEN_CHOICE_REQUIRED;
   }

   enum MtanAuthStepErrors implements StepError {
      MTAN_OTP_WRONG,
      MTAN_OTP_EXPIRED,
      MTAN_OTP_RESEND_REFUSED,
      MTAN_TOKEN_CHOICE_FAILED;
   }

   class MtanNumberChoices implements StepResultDataCollection<AuthenticationFailed.MtanChoiceToken>, Mapifiable {
      private static final String CHOICES_KEY = "choices";
      @NonNull
      private List<AuthenticationFailed.MtanChoiceToken> choices;

      @Override
      public Collection<AuthenticationFailed.MtanChoiceToken> getElements() {
         return this.choices;
      }

      @Override
      public MapifiedValues mapify() {
         return MapifiedValuesBuilder.mapifiedValues()
            .putIfNotEmpty("choices", MapificationUtils.mapifyCollection(this.choices, MtanChoiceTokenMapificationUtil::mapifyMtanChoiceToken))
            .build();
      }

      public static MtanOtpCheckingStep.MtanNumberChoices demapify(MapifiedValues values) {
         return new MtanOtpCheckingStep.MtanNumberChoices(values.demapifyList("choices", MtanChoiceTokenMapificationUtil::demapifyMtanChoiceToken));
      }

      @SuppressFBWarnings(justification = "generated code")
      public MtanNumberChoices(@NonNull List<AuthenticationFailed.MtanChoiceToken> choices) {
         if (choices == null) {
            throw new NullPointerException("choices is marked non-null but is null");
         }

         this.choices = choices;
      }

      @NonNull
      @SuppressFBWarnings(justification = "generated code")
      public List<AuthenticationFailed.MtanChoiceToken> getChoices() {
         return this.choices;
      }

      @SuppressFBWarnings(justification = "generated code")
      public void setChoices(@NonNull List<AuthenticationFailed.MtanChoiceToken> choices) {
         if (choices == null) {
            throw new NullPointerException("choices is marked non-null but is null");
         }

         this.choices = choices;
      }

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

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

      @SuppressFBWarnings(justification = "generated code")
      protected boolean canEqual(Object other) {
         return other instanceof MtanOtpCheckingStep.MtanNumberChoices;
      }

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

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "MtanOtpCheckingStep.MtanNumberChoices(choices=" + this.getChoices() + ")";
      }
   }

   final class MtanOtpResendPossible implements StepResultData {
      private static final String OTP_RESEND_POSSIBLE_KEY = "otpResendPossible";
      private final boolean otpResendPossible;

      public static MtanOtpCheckingStep.MtanOtpResendPossible of(boolean otpResendPossible) {
         return new MtanOtpCheckingStep.MtanOtpResendPossible(otpResendPossible);
      }

      @Override
      public MapifiedValues mapify() {
         return MapifiedValuesBuilder.mapifiedValues().put("otpResendPossible", this.otpResendPossible).build();
      }

      public static MtanOtpCheckingStep.MtanOtpResendPossible demapify(MapifiedValues values) {
         return new MtanOtpCheckingStep.MtanOtpResendPossible(values.<Boolean>get("otpResendPossible"));
      }

      @SuppressFBWarnings(justification = "generated code")
      public MtanOtpResendPossible(boolean otpResendPossible) {
         this.otpResendPossible = otpResendPossible;
      }

      @SuppressFBWarnings(justification = "generated code")
      public boolean isOtpResendPossible() {
         return this.otpResendPossible;
      }

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

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

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "MtanOtpCheckingStep.MtanOtpResendPossible(otpResendPossible=" + this.isOtpResendPossible() + ")";
      }
   }
}
