package com.airlock.iam.transactionapproval.infrastructure.factory;

import com.airlock.iam.base.api.infrastructure.plugin.ModuleForConfig;
import com.airlock.iam.common.api.domain.model.authmethod.AuthenticationMethod;
import com.airlock.iam.core.misc.impl.authen.SimpleAuthenticationMethod;
import com.airlock.iam.factor.application.configuration.airlock2fa.Airlock2FASettings;
import com.airlock.iam.factor.domain.model.airlock2fa.Airlock2FADeviceSettings;
import com.airlock.iam.factor.domain.model.airlock2fa.AuthenticationStatusSettings;
import com.airlock.iam.factor.domain.service.airlock2fa.Airlock2FAApprovalAuthTokenIdService;
import com.airlock.iam.factor.domain.service.airlock2fa.Airlock2FAApprovalService;
import com.airlock.iam.factor.domain.service.airlock2fa.Airlock2FAAuthenticationService;
import com.airlock.iam.factor.domain.service.airlock2fa.AuthenticationStatusService;
import com.airlock.iam.factor.domain.service.airlock2fa.QrCodeImageReader;
import com.airlock.iam.factor.infrastructure.rest.airlock2fa.Airlock2FAApprovalServiceImpl;
import com.airlock.iam.factor.infrastructure.rest.airlock2fa.Airlock2FAAuthenticationServiceImpl;
import com.airlock.iam.factor.infrastructure.rest.airlock2fa.futurae.FuturaeAuthApiDeviceManagementRequestFactory;
import com.airlock.iam.factor.infrastructure.rest.airlock2fa.futurae.FuturaeAuthApiPreAuthenticationRequestFactory;
import com.airlock.iam.factor.infrastructure.rest.airlock2fa.futurae.FuturaeAuthenticationRequestFactory;
import com.airlock.iam.factor.infrastructure.rest.airlock2fa.futurae.FuturaeMessageApprovalRequestFactory;
import com.airlock.iam.factor.infrastructure.rest.airlock2fa.futurae.QrCodeImageReaderImpl;
import com.airlock.iam.flow.api.domain.model.session.FlowSession;
import com.airlock.iam.flow.infrastructure.step.StepSessionModuleHelper;
import com.airlock.iam.flow.shared.domain.model.airlock2fa.Airlock2FAApprovalStepSession;
import com.airlock.iam.flow.shared.domain.model.airlock2fa.Airlock2FAApprovalStepSettings;
import com.airlock.iam.flow.shared.domain.model.airlock2fa.Airlock2FAApprovalStep.Airlock2FAApprovalStepActions;
import com.airlock.iam.flow.shared.domain.model.airlock2fa.Airlock2FAApprovalStep.Airlock2FAApprovalStepErrors;
import com.airlock.iam.flow.shared.infrastructure.factory.Airlock2FAModuleForConfigBase;
import com.airlock.iam.transactionapproval.application.configuration.airlock2fa.Airlock2FATransactionApprovalStepConfig;
import com.airlock.iam.transactionapproval.infrastructure.rest.Airlock2FATransactionApprovalAuthTokenIdServiceImpl;
import com.google.inject.Exposed;
import com.google.inject.Provides;
import java.util.Optional;

@ModuleForConfig(Airlock2FATransactionApprovalStepConfig.class)
public final class Airlock2FATransactionApprovalStepModule extends Airlock2FAModuleForConfigBase {
   @Provides
   @Exposed
   AuthenticationMethod provideAuthenticationMethod() {
      return new SimpleAuthenticationMethod("AIRLOCK_2FA", "transaction approval with Airlock 2FA");
   }

   @Provides
   Airlock2FASettings provideAirlock2faSettings(Airlock2FATransactionApprovalStepConfig config) {
      return config.getAirlock2faSettings();
   }

   @Exposed
   @Provides
   Optional<Airlock2FAApprovalStepSession> provideAirlock2FAApprovalStepSession(FlowSession flowSession) {
      return StepSessionModuleHelper.tryRetrieveStepSession(flowSession, Airlock2FAApprovalStepSession.class);
   }

   @Provides
   @Exposed
   Airlock2FAApprovalStepSettings provideAirlock2FAApprovalStepSettings(Airlock2FATransactionApprovalStepConfig config, Airlock2FASettings airlock2FASettings) {
      return new Airlock2FAApprovalStepSettings(
         new Airlock2FADeviceSettings(config.getApprovalFactors(), config.getCooldownSettings(), airlock2FASettings.getPayloadEncryptionSettings()),
         config.getMobileOnlyRedirectUri(),
         config.getMobileOnlySchemeOverride(),
         airlock2FASettings.isAllowFuturaeBypassMode(),
         config.isEnablePushToAll(),
         config.getShortLivedOnlineQrCodeSettings()
      );
   }

   @Exposed
   @Provides
   Airlock2FAApprovalStepActions provideAirlock2FAApprovalStepActions() {
      return new Airlock2FATransactionApprovalStepConfig.Airlock2FATransactionApprovalStepActions();
   }

   @Exposed
   @Provides
   Airlock2FAApprovalStepErrors provideAirlock2FAApprovalStepErrors() {
      return new Airlock2FATransactionApprovalStepConfig.Airlock2FATransactionApprovalStepErrors();
   }

   @Provides
   AuthenticationStatusSettings provideAuthenticationStatusSettings(Airlock2FASettings airlock2FASettings) {
      return new AuthenticationStatusSettings(airlock2FASettings.isLockUserOnFraud());
   }

   @Exposed
   @Provides
   Optional<Airlock2FAApprovalAuthTokenIdService> provideAirlock2FAApprovalAuthTokenIdService(Airlock2FAApprovalAuthTokenIdService service) {
      return Optional.of(service);
   }

   protected void configure() {
      super.configure();
      this.bind(FuturaeAuthApiPreAuthenticationRequestFactory.class);
      this.bind(FuturaeAuthenticationRequestFactory.class);
      this.bind(FuturaeMessageApprovalRequestFactory.class);
      this.bind(FuturaeAuthApiDeviceManagementRequestFactory.class);
      this.bind(Airlock2FAApprovalService.class).to(Airlock2FAApprovalServiceImpl.class);
      this.expose(Airlock2FAApprovalService.class);
      this.bind(Airlock2FAAuthenticationService.class).to(Airlock2FAAuthenticationServiceImpl.class);
      this.bind(QrCodeImageReader.class).to(QrCodeImageReaderImpl.class);
      this.bind(Airlock2FAApprovalAuthTokenIdService.class).to(Airlock2FATransactionApprovalAuthTokenIdServiceImpl.class);
      this.bind(AuthenticationStatusService.class);
      this.expose(AuthenticationStatusService.class);
   }
}
