package com.airlock.iam.saml2.infrastructure.factory.sp;

import com.airlock.iam.common.domain.service.state.StateRepository;
import com.airlock.iam.common.infrastructure.factory.uri.AbsoluteExternalViewUriFactory;
import com.airlock.iam.openfedlib.saml2.state.Saml2DataMap;
import com.airlock.iam.saml2.application.configuration.SamlConfig;
import com.airlock.iam.saml2.application.service.Saml2LogoutResumeRedirectService;
import com.airlock.iam.saml2.application.service.sp.Saml2SpInitiatedSloService;
import com.airlock.iam.saml2.domain.model.session.FlowFederationSession;
import com.airlock.iam.saml2.infrastructure.Saml2CommonSpaUrls;
import com.airlock.iam.saml2.infrastructure.service.Saml2LogoutResumeRedirectServiceImpl;
import com.airlock.iam.saml2.infrastructure.service.sp.logout.Saml2SpInitiatedSloServiceImpl;
import com.airlock.iam.saml2.infrastructure.sp.logout.Saml2SpInitiatedSloFederationSessionCache;
import com.airlock.iam.saml2.infrastructure.sp.logout.Saml2SpInitiatedSloFederationSessionCacheImpl;
import com.airlock.iam.saml2.infrastructure.state.FlowFederationSessionSerializer;
import com.airlock.iam.saml2.infrastructure.state.StateStoreBackedSaml2DataMap;
import com.google.inject.PrivateModule;
import com.google.inject.Provides;
import com.google.inject.servlet.RequestScoped;
import jakarta.inject.Provider;
import java.net.URI;
import java.util.regex.Pattern;

public final class Saml2SpInitiatedSloServiceModule extends PrivateModule {
   @Provides
   Saml2DataMap<FlowFederationSession> provideFlowFederationSessionDataMap(Provider<StateRepository> stateStore) {
      return new StateStoreBackedSaml2DataMap<>(stateStore, "Saml2SpInitiatedSloId", new FlowFederationSessionSerializer());
   }

   @Provides
   Pattern provideUiLogoutResumeUriPattern(SamlConfig config, AbsoluteExternalViewUriFactory externalViewUriFactory) {
      return config.getCustomLogoutResumeUriPattern().orElse(allowLocalLogoutResumePattern(externalViewUriFactory));
   }

   @Provides
   URI provideSpLogoutUri(SamlConfig samlConfig) {
      return samlConfig.getCustomSpLogoutUri().orElse(Saml2CommonSpaUrls.UI_LOGOUT_URI.uri());
   }

   private static Pattern allowLocalLogoutResumePattern(AbsoluteExternalViewUriFactory externalViewUriFactory) {
      return Pattern.compile(Pattern.quote(externalViewUriFactory.createAbsoluteUri(Saml2CommonSpaUrls.UI_LOGOUT_RESUME_URI.uri()).toASCIIString()));
   }

   protected void configure() {
      this.bind(Saml2SpInitiatedSloFederationSessionCache.class).to(Saml2SpInitiatedSloFederationSessionCacheImpl.class);
      this.bind(Saml2SpInitiatedSloService.class).to(Saml2SpInitiatedSloServiceImpl.class);
      this.bind(Saml2LogoutResumeRedirectService.class).to(Saml2LogoutResumeRedirectServiceImpl.class).in(RequestScoped.class);
      this.expose(Saml2SpInitiatedSloService.class);
   }
}
