package com.airlock.iam.flow.shared.infrastructure.factory;

import com.airlock.iam.base.api.domain.model.exception.FailureException;
import com.airlock.iam.flow.application.configuration.FlowConfig;
import com.airlock.iam.flow.application.configuration.FlowConfigRepository;
import com.airlock.iam.flow.shared.application.configuration.FlowRequestAttributeConfig;
import com.airlock.iam.flow.shared.application.configuration.FlowUserNameTransformerConfig;
import com.airlock.iam.flow.shared.domain.model.session.MultiFlowCapableUserSession;
import com.google.inject.Exposed;
import com.google.inject.PrivateModule;
import com.google.inject.Provides;
import jakarta.inject.Provider;
import java.util.Optional;

public final class FlowConfigModule extends PrivateModule {
   @Exposed
   @Provides
   FlowConfig provideFlowConfig(Optional<FlowConfig> optionalFlowConfig, Provider<FlowConfigRepository> flowConfigRepository) {
      return optionalFlowConfig.or(((FlowConfigRepository)flowConfigRepository.get())::getDefaultFlowConfig)
         .orElseThrow(() -> new FailureException("No current flow and no default flow to get FlowConfig"));
   }

   @Exposed
   @Provides
   Optional<FlowConfig> provideOptionalFlowConfig(MultiFlowCapableUserSession userSession, Provider<FlowConfigRepository> flowConfigRepository) {
      return userSession.getCurrentFlowSession()
         .flatMap(flowSession -> ((FlowConfigRepository)flowConfigRepository.get()).getFlowConfigByConfigHash(flowSession.getFlowConfigHash()));
   }

   @Exposed
   @Provides
   Optional<FlowUserNameTransformerConfig> provideFlowUserNameTransformerConfig(FlowConfig flowConfig) {
      return Optional.of(flowConfig).filter(FlowUserNameTransformerConfig.class::isInstance).map(FlowUserNameTransformerConfig.class::cast);
   }

   @Exposed
   @Provides
   Optional<FlowRequestAttributeConfig> provideFlowRequestAttributeConfig(FlowConfig flowConfig) {
      return Optional.of(flowConfig).filter(FlowRequestAttributeConfig.class::isInstance).map(FlowRequestAttributeConfig.class::cast);
   }

   protected void configure() {
   }
}
