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

import com.airlock.iam.authentication.application.configuration.airlock2fa.Airlock2FAUsernamelessQrCodeAuthenticationStepConfig;
import com.airlock.iam.authentication.domain.model.airlock2fa.Airlock2FAUsernamelessQrCodeAuthenticationStepSession;
import com.airlock.iam.authentication.domain.model.airlock2fa.Airlock2FAUsernamelessStepSettings;
import com.airlock.iam.base.api.infrastructure.plugin.ModuleForConfig;
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.Airlock2FAFactor;
import com.airlock.iam.factor.domain.model.airlock2fa.Airlock2FAFactorPriority;
import com.airlock.iam.factor.domain.model.airlock2fa.AuthenticationStatusSettings;
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.Airlock2FAAuthenticationServiceImpl;
import com.airlock.iam.factor.infrastructure.rest.airlock2fa.futurae.FuturaeAuthenticationRequestFactory;
import com.airlock.iam.factor.infrastructure.rest.airlock2fa.futurae.QrCodeImageReaderImpl;
import com.airlock.iam.flow.api.application.configuration.step.StepIdConfig;
import com.airlock.iam.flow.api.domain.model.session.FlowSession;
import com.airlock.iam.flow.infrastructure.step.StepSessionModuleHelper;
import com.airlock.iam.flow.shared.infrastructure.factory.Airlock2FAModuleForConfigBase;
import com.google.inject.Exposed;
import com.google.inject.Provides;
import java.time.Duration;
import java.util.Optional;

@ModuleForConfig(Airlock2FAUsernamelessQrCodeAuthenticationStepConfig.class)
public final class Airlock2FAUsernamelessQrCodeAuthenticationStepModule extends Airlock2FAModuleForConfigBase {
   @Exposed
   @Provides
   Optional<Airlock2FAUsernamelessQrCodeAuthenticationStepSession> provideAirlock2FAUsernamelessQrCodeAuthenticationStepSession(FlowSession flowSession) {
      return StepSessionModuleHelper.tryRetrieveStepSession(flowSession, Airlock2FAUsernamelessQrCodeAuthenticationStepSession.class);
   }

   @Exposed
   @Provides
   Airlock2FASettings provideAirlock2FASettings(Airlock2FAUsernamelessQrCodeAuthenticationStepConfig config) {
      return config.getAirlock2faSettings();
   }

   @Exposed
   @Provides
   Airlock2FAUsernamelessStepSettings provideAirlock2FAUsernamelessQrCodeAuthenticationStepSettings(
      Airlock2FAUsernamelessQrCodeAuthenticationStepConfig config, Airlock2FASettings airlock2FASettings
   ) {
      return new Airlock2FAUsernamelessStepSettings(
         config.getMaxRenewals(),
         Duration.ofSeconds(config.getQrCodeValidity()),
         Optional.ofNullable(config.getTimeoutGoto()).map(StepIdConfig::getId),
         new Airlock2FADeviceSettings(
            Airlock2FAFactorPriority.of(Airlock2FAFactor.USERNAMELESS_QR_CODE), config.getCooldownSettings(), airlock2FASettings.getPayloadEncryptionSettings()
         )
      );
   }

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

   @Override
   protected void configure() {
      super.configure();
      this.bind(FuturaeAuthenticationRequestFactory.class);
      this.bind(Airlock2FAAuthenticationService.class).to(Airlock2FAAuthenticationServiceImpl.class);
      this.expose(Airlock2FAAuthenticationService.class);
      this.bind(AuthenticationStatusService.class);
      this.expose(AuthenticationStatusService.class);
      this.bind(QrCodeImageReader.class).to(QrCodeImageReaderImpl.class);
   }
}
