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

import com.airlock.iam.admin.application.configuration.users.UsersConfiguration;
import com.airlock.iam.admin.application.service.token.password.PasswordAdminService;
import com.airlock.iam.admin.application.service.user.UserAdminService;
import com.airlock.iam.admin.application.service.user.validation.UserPasswordValidator;
import com.airlock.iam.admin.application.service.user.validation.UsernameFormatValidator;
import com.airlock.iam.admin.application.service.user.validation.UsernameUniquenessValidator;
import com.airlock.iam.base.api.domain.model.validation.Validator;
import com.airlock.iam.base.api.infrastructure.plugin.PluginConfigToLogic;
import com.airlock.iam.common.api.domain.model.password.Password;
import com.airlock.iam.common.api.domain.model.store.user.UserStore;
import com.airlock.iam.common.application.configuration.user.UniversalUniqueIdentityGenerator;
import com.airlock.iam.common.application.service.password.PasswordPolicyValidator;
import com.airlock.iam.core.domain.model.user.UserIdentityGenerator;
import com.airlock.iam.core.domain.model.validation.MultiValidator;
import com.google.inject.PrivateModule;
import com.google.inject.Provides;
import com.google.inject.servlet.RequestScoped;
import jakarta.inject.Named;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public final class UserAdminServiceModule extends PrivateModule {
   @Provides
   UserIdentityGenerator provideUserIdentityGenerator(Optional<UsersConfiguration> usersConfig) {
      return usersConfig.flatMap(UsersConfiguration::getUserIdentityGenerator).orElseGet(UniversalUniqueIdentityGenerator::new);
   }

   @Provides
   UserStore provideUserStore(@Named("MANAGED_USERS_STORE") UserStore userStore) {
      return userStore;
   }

   @Provides
   Validator<Password> providePasswordValidator(Optional<PasswordAdminService> passwordService) {
      return UserPasswordValidator.builder().passwordService(passwordService).passwordPolicyValidator(new PasswordPolicyValidator()).build();
   }

   @Provides
   Validator<String> provideCombinedUsernameValidators(UserStore userStore, Optional<UsersConfiguration> usersConfig, PluginConfigToLogic toLogic) {
      List<Validator<String>> validators = new ArrayList<>();
      validators.add(new UsernameFormatValidator());
      validators.add(new UsernameUniquenessValidator(userStore));
      configurableUsernameValidator(usersConfig, toLogic).ifPresent(validators::add);
      return MultiValidator.withValidators(validators);
   }

   private static Optional<Validator<String>> configurableUsernameValidator(Optional<UsersConfiguration> usersConfig, PluginConfigToLogic toLogic) {
      return usersConfig.flatMap(UsersConfiguration::getUsernameValidator).map(toLogic::getLogic);
   }

   protected void configure() {
      this.bind(UserAdminService.class).in(RequestScoped.class);
      this.expose(UserAdminService.class);
   }
}
