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

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.Saml2FlowIdpConfig;
import com.airlock.iam.saml2.application.service.Saml2LogoutResumeRedirectService;
import com.airlock.iam.saml2.application.service.idp.Saml2IdpInitiatedStartSloService;
import com.airlock.iam.saml2.domain.model.session.FlowFederationSession;
import com.airlock.iam.saml2.infrastructure.Saml2CommonSpaUrls;
import com.airlock.iam.saml2.infrastructure.idp.logout.Saml2IdpInitiatedSloFederationSessionCache;
import com.airlock.iam.saml2.infrastructure.idp.logout.Saml2IdpInitiatedSloFederationSessionCacheImpl;
import com.airlock.iam.saml2.infrastructure.service.Saml2LogoutResumeRedirectServiceImpl;
import com.airlock.iam.saml2.infrastructure.service.idp.logout.Saml2IdpInitiatedStartSloServiceImpl;
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 jakarta.inject.Provider;
import java.net.URI;
import java.util.regex.Pattern;

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

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

   @Provides
   URI provideLogoutUri(Saml2FlowIdpConfig config) {
      return config.getCustomLogoutUri().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(Saml2IdpInitiatedSloFederationSessionCache.class).to(Saml2IdpInitiatedSloFederationSessionCacheImpl.class);
      this.bind(Saml2IdpInitiatedStartSloService.class).to(Saml2IdpInitiatedStartSloServiceImpl.class);
      this.bind(Saml2LogoutResumeRedirectService.class).to(Saml2LogoutResumeRedirectServiceImpl.class);
      this.expose(Saml2IdpInitiatedStartSloService.class);
   }
}
