package com.airlock.iam.factor.domain.service.airlock2fa;

import com.airlock.iam.airlock2fa.api.domain.model.Airlock2FAAccountId;
import com.airlock.iam.airlock2fa.api.domain.model.Airlock2FADeviceId;
import com.airlock.iam.base.misc.result.Result;
import com.airlock.iam.factor.domain.model.airlock2fa.Airlock2FAAuthDevice;
import com.airlock.iam.factor.domain.model.airlock2fa.Airlock2FAAuthenticationException;
import com.airlock.iam.factor.domain.model.airlock2fa.Airlock2FAMobileOnlyRedirectUri;
import com.airlock.iam.factor.domain.model.airlock2fa.Airlock2FASessionId;
import com.airlock.iam.factor.domain.model.airlock2fa.Airlock2FAUserPresenceVerification;
import com.airlock.iam.factor.domain.model.airlock2fa.AuthenticationStatus;
import com.airlock.iam.factor.domain.model.airlock2fa.DeferredAuthenticationAnswer;
import com.airlock.iam.factor.domain.model.airlock2fa.ImmediateAuthenticationAnswer;
import com.airlock.iam.factor.domain.model.airlock2fa.futurae.Airlock2FAFuturaeAuthSession;
import com.airlock.iam.factor.domain.model.airlock2fa.futurae.FuturaeErrorResponseException;
import com.airlock.iam.factor.domain.model.airlock2fa.otp.Airlock2FAOtp;
import com.airlock.iam.factor.domain.model.airlock2fa.otp.Airlock2FAPasscode;
import com.airlock.iam.factor.domain.model.airlock2fa.qrcode.Airlock2FAExchangeTokensAnswer;
import com.airlock.iam.factor.domain.model.airlock2fa.qrcode.Airlock2FAQrCodeImage;
import com.airlock.iam.factor.domain.model.airlock2fa.qrcode.Airlock2FAQrCodeUrl;
import com.airlock.iam.flow.shared.api.domain.model.message.Airlock2FAMessage;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.time.Duration;
import java.util.Optional;

public interface Airlock2FAAuthenticationService extends Airlock2FAPreAuthenticationService {
   DeferredAuthenticationAnswer.UsernamelessQrCodeDeferredAuthenticationAnswer authenticateWithUsernamelessQrCode(
      Duration var1, Optional<Airlock2FAMessage> var2
   ) throws Airlock2FAAuthenticationException;

   ImmediateAuthenticationAnswer authenticateWithPasscode(Airlock2FAAccountId var1, Airlock2FAPasscode var2) throws Airlock2FAAuthenticationException;

   SessionBasedAuthenticationAnswer.OneTouchAuthenticationAnswer authenticateWithOneTouch(
      Airlock2FAAccountId var1, Airlock2FAAuthDevice var2, Airlock2FAMessage var3
   ) throws Airlock2FAAuthenticationException;

   SessionBasedAuthenticationAnswer.OneTouchAuthenticationAnswer authenticateWithPushToAll(Airlock2FAAccountId var1, Airlock2FAMessage var2) throws Airlock2FAAuthenticationException;

   SessionBasedAuthenticationAnswer.OnlineQrCodeAuthenticationAnswer authenticateWithOnlineQrCode(
      Airlock2FAAccountId var1, Optional<Airlock2FAMessage> var2, Optional<Duration> var3
   ) throws Airlock2FAAuthenticationException;

   SessionBasedAuthenticationAnswer.MobileOnlyAuthenticationAnswer authenticateWithMobileOnly(
      Airlock2FAAccountId var1, Optional<Airlock2FAMobileOnlyRedirectUri> var2
   ) throws Airlock2FAAuthenticationException;

   SessionBasedAuthenticationAnswer.OfflineQrCodeAuthenticationAnswer authenticateWithOfflineQrCode(
      Airlock2FAAccountId var1, Airlock2FAAuthDevice var2, Optional<Airlock2FAMessage> var3
   );

   default SessionBasedAuthenticationAnswer.OfflineQrCodeAuthenticationAnswer authenticateWithOfflineQrCode(
      Airlock2FAAccountId accountId, Airlock2FAAuthDevice device
   ) {
      return this.authenticateWithOfflineQrCode(accountId, device, Optional.empty());
   }

   Airlock2FAQrCodeImage retrieveOfflineQrCodeImage(Airlock2FAAccountId var1, Airlock2FAQrCodeUrl var2) throws Airlock2FAAuthenticationException;

   Result<Airlock2FAAuthenticationService.ValidateOfflineQrCodeAnswer, FuturaeErrorResponseException> validateOfflineQrCode(
      Airlock2FAAccountId var1, Airlock2FASessionId var2, Airlock2FAOtp var3
   );

   Airlock2FAAuthenticationService.AuthenticationStatusAnswer checkAuthenticationStatus(Airlock2FAFuturaeAuthSession var1) throws Airlock2FAAuthenticationException;

   Result<Airlock2FAAuthenticationService.AuthenticationStatusAnswer, FuturaeErrorResponseException> checkAuthenticationStatusUsernameless(
      Airlock2FASessionId var1
   );

   Result<ImmediateAuthenticationAnswer, FuturaeErrorResponseException> abortAuthentication(Airlock2FAAccountId var1, Airlock2FASessionId var2);

   Airlock2FAExchangeTokensAnswer fetchAuthenticationExchangeTokens(
      Airlock2FAAccountId var1, Airlock2FASessionId var2, Duration var3, int var4, String var5, String var6
   );

   final class AuthenticationStatusAnswer {
      private final Airlock2FAAuthenticationService.AuthenticationStatusResult result;
      private final Optional<AuthenticationStatus> status;
      private final Optional<Airlock2FADeviceId> deviceId;
      private final Optional<Airlock2FAUserPresenceVerification> userPresenceVerification;
      private final Optional<Airlock2FAAccountId> accountId;

      public AuthenticationStatusAnswer(Airlock2FAAuthenticationService.AuthenticationStatusResult result) {
         this(result, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty());
      }

      public AuthenticationStatusAnswer(
         Airlock2FAAuthenticationService.AuthenticationStatusResult result,
         Optional<AuthenticationStatus> status,
         Optional<Airlock2FADeviceId> deviceId,
         Optional<Airlock2FAUserPresenceVerification> userPresenceVerification,
         Optional<Airlock2FAAccountId> accountId
      ) {
         this.result = result;
         this.status = status;
         this.deviceId = deviceId;
         this.userPresenceVerification = userPresenceVerification;
         this.accountId = accountId;
      }

      public boolean isTimeoutRetry() {
         return this.result == Airlock2FAAuthenticationService.AuthenticationStatusResult.DENY
            && this.status.<Boolean>map(s -> s == AuthenticationStatus.TIMEOUT_RETRY).orElse(false);
      }

      @SuppressFBWarnings(justification = "generated code")
      public Airlock2FAAuthenticationService.AuthenticationStatusResult getResult() {
         return this.result;
      }

      @SuppressFBWarnings(justification = "generated code")
      public Optional<AuthenticationStatus> getStatus() {
         return this.status;
      }

      @SuppressFBWarnings(justification = "generated code")
      public Optional<Airlock2FADeviceId> getDeviceId() {
         return this.deviceId;
      }

      @SuppressFBWarnings(justification = "generated code")
      public Optional<Airlock2FAUserPresenceVerification> getUserPresenceVerification() {
         return this.userPresenceVerification;
      }

      @SuppressFBWarnings(justification = "generated code")
      public Optional<Airlock2FAAccountId> getAccountId() {
         return this.accountId;
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public boolean equals(Object o) {
         if (o == this) {
            return true;
         } else if (!(o instanceof Airlock2FAAuthenticationService.AuthenticationStatusAnswer other)) {
            return false;
         } else {
            Object this$result = this.result;
            Object other$result = other.result;
            if (this$result == null ? other$result == null : this$result.equals(other$result)) {
               Object this$status = this.status;
               Object other$status = other.status;
               if (this$status == null ? other$status == null : this$status.equals(other$status)) {
                  Object this$deviceId = this.deviceId;
                  Object other$deviceId = other.deviceId;
                  if (this$deviceId == null ? other$deviceId == null : this$deviceId.equals(other$deviceId)) {
                     Object this$userPresenceVerification = this.userPresenceVerification;
                     Object other$userPresenceVerification = other.userPresenceVerification;
                     if (this$userPresenceVerification == null
                        ? other$userPresenceVerification == null
                        : this$userPresenceVerification.equals(other$userPresenceVerification)) {
                        Object this$accountId = this.accountId;
                        Object other$accountId = other.accountId;
                        return this$accountId == null ? other$accountId == null : this$accountId.equals(other$accountId);
                     } else {
                        return false;
                     }
                  } else {
                     return false;
                  }
               } else {
                  return false;
               }
            } else {
               return false;
            }
         }
      }

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

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "Airlock2FAAuthenticationService.AuthenticationStatusAnswer(result="
            + this.getResult()
            + ", status="
            + this.getStatus()
            + ", deviceId="
            + this.getDeviceId()
            + ", userPresenceVerification="
            + this.getUserPresenceVerification()
            + ", accountId="
            + this.getAccountId()
            + ")";
      }

      @SuppressFBWarnings(justification = "generated code")
      public Airlock2FAAuthenticationService.AuthenticationStatusAnswer withResult(Airlock2FAAuthenticationService.AuthenticationStatusResult result) {
         return this.result == result
            ? this
            : new Airlock2FAAuthenticationService.AuthenticationStatusAnswer(result, this.status, this.deviceId, this.userPresenceVerification, this.accountId);
      }

      @SuppressFBWarnings(justification = "generated code")
      public Airlock2FAAuthenticationService.AuthenticationStatusAnswer withStatus(Optional<AuthenticationStatus> status) {
         return this.status == status
            ? this
            : new Airlock2FAAuthenticationService.AuthenticationStatusAnswer(this.result, status, this.deviceId, this.userPresenceVerification, this.accountId);
      }

      @SuppressFBWarnings(justification = "generated code")
      public Airlock2FAAuthenticationService.AuthenticationStatusAnswer withDeviceId(Optional<Airlock2FADeviceId> deviceId) {
         return this.deviceId == deviceId
            ? this
            : new Airlock2FAAuthenticationService.AuthenticationStatusAnswer(this.result, this.status, deviceId, this.userPresenceVerification, this.accountId);
      }

      @SuppressFBWarnings(justification = "generated code")
      public Airlock2FAAuthenticationService.AuthenticationStatusAnswer withUserPresenceVerification(
         Optional<Airlock2FAUserPresenceVerification> userPresenceVerification
      ) {
         return this.userPresenceVerification == userPresenceVerification
            ? this
            : new Airlock2FAAuthenticationService.AuthenticationStatusAnswer(this.result, this.status, this.deviceId, userPresenceVerification, this.accountId);
      }

      @SuppressFBWarnings(justification = "generated code")
      public Airlock2FAAuthenticationService.AuthenticationStatusAnswer withAccountId(Optional<Airlock2FAAccountId> accountId) {
         return this.accountId == accountId
            ? this
            : new Airlock2FAAuthenticationService.AuthenticationStatusAnswer(this.result, this.status, this.deviceId, this.userPresenceVerification, accountId);
      }
   }

   enum AuthenticationStatusResult {
      ALLOW("allow", true),
      DENY("deny", true),
      WAITING("waiting", false),
      TIMEOUT("timeout", true);

      private final String value;
      private final boolean finalResult;

      @SuppressFBWarnings(justification = "generated code")
      AuthenticationStatusResult(final String value, final boolean finalResult) {
         this.value = value;
         this.finalResult = finalResult;
      }

      @SuppressFBWarnings(justification = "generated code")
      public String getValue() {
         return this.value;
      }

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

   enum OfflineValidationResult {
      ALLOW("allow", true),
      DENY("deny", true),
      WAITING("waiting", false);

      private final String value;
      private final boolean finalResult;

      @SuppressFBWarnings(justification = "generated code")
      OfflineValidationResult(final String value, final boolean finalResult) {
         this.value = value;
         this.finalResult = finalResult;
      }

      @SuppressFBWarnings(justification = "generated code")
      public String getValue() {
         return this.value;
      }

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

   final class ValidateOfflineQrCodeAnswer {
      private final Airlock2FAAuthenticationService.OfflineValidationResult result;
      private final Optional<Airlock2FADeviceId> deviceId;

      public ValidateOfflineQrCodeAnswer(Airlock2FAAuthenticationService.OfflineValidationResult result, Optional<Airlock2FADeviceId> deviceId) {
         this.result = result;
         this.deviceId = deviceId;
      }

      public ValidateOfflineQrCodeAnswer(Airlock2FAAuthenticationService.OfflineValidationResult result) {
         this.result = result;
         this.deviceId = Optional.empty();
      }

      @SuppressFBWarnings(justification = "generated code")
      public Airlock2FAAuthenticationService.OfflineValidationResult getResult() {
         return this.result;
      }

      @SuppressFBWarnings(justification = "generated code")
      public Optional<Airlock2FADeviceId> getDeviceId() {
         return this.deviceId;
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public boolean equals(Object o) {
         if (o == this) {
            return true;
         } else if (!(o instanceof Airlock2FAAuthenticationService.ValidateOfflineQrCodeAnswer other)) {
            return false;
         } else {
            Object this$result = this.result;
            Object other$result = other.result;
            if (this$result == null ? other$result == null : this$result.equals(other$result)) {
               Object this$deviceId = this.deviceId;
               Object other$deviceId = other.deviceId;
               return this$deviceId == null ? other$deviceId == null : this$deviceId.equals(other$deviceId);
            } else {
               return false;
            }
         }
      }

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

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "Airlock2FAAuthenticationService.ValidateOfflineQrCodeAnswer(result=" + this.getResult() + ", deviceId=" + this.getDeviceId() + ")";
      }
   }
}
