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

import com.airlock.iam.authentication.api.domain.model.step.AuthenticationStepResult;
import com.airlock.iam.authentication.api.domain.model.step.AuthenticationStepResultFactory;
import com.airlock.iam.base.api.domain.model.exception.FailureException;
import com.airlock.iam.core.misc.authen.result.AuthenticationFailed;
import com.airlock.iam.core.misc.authen.result.AuthenticationFailedToken;
import com.airlock.iam.core.misc.authen.result.AuthenticationResult;
import com.airlock.iam.flow.api.domain.model.step.GenericStepError;

public final class GenericOtpCheckingResultMapper {
   public static AuthenticationStepResult mapAuthenticationResult(AuthenticationResult result, AuthenticationStepResultFactory stepResultFactory) {
      if (result.authenticationSucceeded()) {
         return stepResultFactory.success().build();
      } else if (result.isOfType(AuthenticationFailedToken.TOKEN_REQUIRED)) {
         return stepResultFactory.stay(GenericOtpCheckingStep.GenericOtpStepActions.OTP_REQUIRED).build();
      } else if (result.isOfType(AuthenticationFailed.CREDENTIAL_NOT_ASSIGNED) || result.isOfType(AuthenticationFailed.CREDENTIAL_INACTIVE)) {
         return stepResultFactory.fail(GenericStepError.NO_VALID_TOKEN).build();
      } else if (result.isOfType(AuthenticationFailedToken.TOKEN_WRONG)) {
         return stepResultFactory.fail(GenericOtpCheckingStep.GenericOtpStepErrors.OTP_WRONG).build();
      } else if (result.isOfType(AuthenticationFailedToken.TOKEN_WRONG_TRY_AGAIN)) {
         return stepResultFactory.failRetry(GenericOtpCheckingStep.GenericOtpStepErrors.OTP_WRONG, GenericOtpCheckingStep.GenericOtpStepActions.OTP_REQUIRED)
            .build();
      } else if (result.isOfType(AuthenticationFailedToken.TOKEN_EXPIRED)) {
         return stepResultFactory.fail(GenericOtpCheckingStep.GenericOtpStepErrors.OTP_EXPIRED).build();
      } else if (result.isOfType(AuthenticationFailedToken.NEXT_TOKEN_REQUIRED)) {
         return stepResultFactory.stay(GenericOtpCheckingStep.GenericOtpStepActions.NEXT_OTP_REQUIRED).build();
      } else if (!result.requiresMoreSteps()) {
         return stepResultFactory.fail(GenericOtpCheckingStep.GenericOtpStepErrors.OTP_WRONG).build();
      } else {
         throw new FailureException("Unmappable authentication result: " + result);
      }
   }

   private GenericOtpCheckingResultMapper() {
   }
}
