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

import com.airlock.iam.base.api.domain.model.exception.FailureException;
import com.airlock.iam.base.api.domain.model.exception.ServiceConfigurationException;
import com.airlock.iam.base.api.infrastructure.plugin.ModuleForConfig;
import com.airlock.iam.common.application.configuration.accountlink.persistence.AccountLinkPersisterConfig;
import com.airlock.iam.common.domain.model.provider.ProviderId;
import com.airlock.iam.common.domain.service.accountlink.persistence.AccountLinkPersister;
import com.airlock.iam.flow.api.domain.model.redflag.RedFlag;
import com.airlock.iam.oauth2.application.configuration.OAuth2ClientSettingsConfigSpec;
import com.airlock.iam.oauth2.application.configuration.OAuth2SsoFlowClientSettingsBase;
import com.airlock.iam.oauth2.application.configuration.accountlinking.MissingAccountLinkStepConfig;
import com.airlock.iam.oauth2.domain.service.accountlinking.AccountLinkRepository;
import com.airlock.iam.oauth2.domain.service.accountlinking.AccountLinkRepositoryImpl;
import com.google.inject.Exposed;
import com.google.inject.PrivateModule;
import com.google.inject.Provides;
import java.util.Optional;

@ModuleForConfig(MissingAccountLinkStepConfig.class)
public final class MissingAccountLinkStepModule extends PrivateModule {
   @Provides
   @Exposed
   RedFlag provideRedFlag(MissingAccountLinkStepConfig config) {
      return config.getRedFlag().toRedFlag();
   }

   @Provides
   @Exposed
   ProviderId provideProviderId() {
      throw new FailureException("implement: read from session attribute");
   }

   @Provides
   @Exposed
   OAuth2SsoFlowClientSettingsBase provideFlowClientSettings(ProviderId providerId, Optional<OAuth2ClientSettingsConfigSpec> clientSettings) {
      Optional<OAuth2SsoFlowClientSettingsBase> stepClientSettings = clientSettings.flatMap(spec -> spec.findFlowClientSettings(providerId));
      return ServiceConfigurationException.checkPresent(
         stepClientSettings, String.format("No OAuth 2.0 flow based settings with provider %s configured in OAuth 2.0 SSO settings.", providerId.id())
      );
   }

   @Provides
   @Exposed
   AccountLinkRepository provideAccountLinkRepository(Optional<OAuth2ClientSettingsConfigSpec> configSpecOptional) {
      AccountLinkPersister accountLinkPersister = ServiceConfigurationException.checkPresent(
         configSpecOptional.map(OAuth2ClientSettingsConfigSpec::getAccountLinkPersister).map(AccountLinkPersisterConfig::persister),
         "No Account Link Persister configured in OAuth 2.0/OIDC Client settings."
      );
      return AccountLinkRepositoryImpl.builder().persister(accountLinkPersister).build();
   }

   protected void configure() {
   }
}
