package com.airlock.iam.admin.infrastructure.factory.prot;

import com.airlock.iam.admin.application.configuration.users.UsersConfiguration;
import com.airlock.iam.admin.application.service.user.rememberme.RememberMeAdminLogger;
import com.airlock.iam.admin.application.service.user.rememberme.RememberMeAdminLoggerImpl;
import com.airlock.iam.admin.application.service.user.rememberme.RememberMeJspPersisterService;
import com.airlock.iam.admin.application.service.user.rememberme.RememberMeJspPersisterServiceImpl;
import com.airlock.iam.admin.application.service.user.rememberme.RememberMeManagementService;
import com.airlock.iam.admin.application.service.user.rememberme.RememberMeManagementServiceImpl;
import com.airlock.iam.admin.domain.model.rememberme.RememberMeTokenAdminRepository;
import com.airlock.iam.admin.infrastructure.service.rememberme.RememberMeTokenAdminRepositoryImpl;
import com.airlock.iam.base.api.domain.model.exception.ServiceConfigurationException;
import com.airlock.iam.common.application.configuration.rememberme.JspRememberMeConfig;
import com.airlock.iam.common.application.configuration.rememberme.RememberMeConfig;
import com.airlock.iam.common.application.configuration.rememberme.RememberMeRepositoryConfig;
import com.airlock.iam.core.misc.persistency.CredentialPersister;
import com.airlock.iam.database.infrastructure.JooqConfig;
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;

public class RememberMeServiceModule extends PrivateModule {
   @Provides
   @RequestScoped
   Optional<CredentialPersister> provideCredentialPersister(Optional<UsersConfiguration> usersConfiguration) {
      ensureUsersConfigurationPresent(usersConfiguration);
      return usersConfiguration.flatMap(UsersConfiguration::getJspLoginappRememberMeSettings).map(JspRememberMeConfig::getCredentialPersister);
   }

   @Provides
   @RequestScoped
   Optional<RememberMeJspPersisterService> provideRememberMePersisterService(Optional<CredentialPersister> credentialPersister) {
      return credentialPersister.map(RememberMeJspPersisterServiceImpl::new);
   }

   @Provides
   @RequestScoped
   Optional<RememberMeTokenAdminRepository> provideRepository(Optional<UsersConfiguration> usersConfiguration) {
      ensureUsersConfigurationPresent(usersConfiguration);
      return usersConfiguration.filter(UsersConfiguration::isRememberMeManagementEnabled)
         .flatMap(UsersConfiguration::getFlowRememberMeSettings)
         .map(RememberMeConfig::getRepository)
         .<JooqConfig>map(RememberMeRepositoryConfig::jooqConfig)
         .map(RememberMeTokenAdminRepositoryImpl::new);
   }

   @Provides
   @RequestScoped
   @Exposed
   Optional<RememberMeManagementService> provideRememberMeManagementService(
      Optional<RememberMeJspPersisterService> persister, Optional<RememberMeTokenAdminRepository> repository, RememberMeAdminLogger logger
   ) {
      return persister.isEmpty() && repository.isEmpty()
         ? Optional.empty()
         : Optional.of(RememberMeManagementServiceImpl.builder().jspTokenPersister(persister).flowTokenRepository(repository).logger(logger).build());
   }

   protected void configure() {
      this.bind(RememberMeAdminLogger.class).to(RememberMeAdminLoggerImpl.class).in(RequestScoped.class);
   }

   private static void ensureUsersConfigurationPresent(Optional<UsersConfiguration> usersConfiguration) {
      ServiceConfigurationException.checkPresent(usersConfiguration, "users not configured");
   }
}
