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

import com.airlock.iam.base.misc.time.RealTimeProvider;
import com.airlock.iam.base.misc.time.TimeProvider;
import com.airlock.iam.common.api.domain.model.request.Request;
import com.airlock.iam.common.application.configuration.logging.CorrelationIdSettingsConfig;
import com.airlock.iam.common.domain.model.gateway.WafSettings;
import com.airlock.iam.common.domain.model.logs.CorrelationIdSettings;
import com.airlock.iam.common.domain.model.state.StateLockId;
import com.airlock.iam.common.infrastructure.filter.auth.HttpServletRequestToRequestAdapter;
import com.airlock.iam.core.application.configuration.waf.AirlockGatewayConfig;
import com.airlock.iam.system.version.CurrentVersion;
import com.airlock.iam.system.version.IamVersion;
import com.google.inject.Exposed;
import com.google.inject.PrivateModule;
import com.google.inject.Provides;
import com.google.inject.servlet.RequestScoped;
import java.util.Optional;
import java.util.UUID;

public final class CommonRestInfrastructureModule extends PrivateModule {
   @Provides
   @RequestScoped
   @Exposed
   Optional<WafSettings> wafSettings(Optional<AirlockGatewayConfig> airlockConfig) {
      return airlockConfig.map(
         c -> WafSettings.builder(c.getControlCookieName(), c.getEnvironmentCookiePrefix())
            .mustAddCredentialsToSession(c.mustAddCredentialsToSession())
            .build()
      );
   }

   @Provides
   @RequestScoped
   @Exposed
   Optional<CorrelationIdSettings> correlationIdSettings(Optional<CorrelationIdSettingsConfig> correlationIdSettingsConfig) {
      return correlationIdSettingsConfig.map(
         config -> CorrelationIdSettings.builder().headerName(config.getHeaderName()).validationPattern(config.getValidationPattern()).build()
      );
   }

   @Exposed
   @RequestScoped
   @Provides
   StateLockId provideStateLockId() {
      return new StateLockId(UUID.randomUUID().toString());
   }

   protected void configure() {
      this.bind(IamVersion.class).toInstance((IamVersion)CurrentVersion.get().orElseThrow());
      this.expose(IamVersion.class);
      this.bind(TimeProvider.class).toInstance(new RealTimeProvider());
      this.expose(TimeProvider.class);
      this.bind(Request.class).to(HttpServletRequestToRequestAdapter.class).in(RequestScoped.class);
      this.expose(Request.class);
   }
}
