package com.airlock.iam.flow.shared.domain.service.identification;

import com.airlock.iam.base.api.domain.model.store.query.Restriction;
import com.airlock.iam.base.api.domain.model.store.query.StringField;
import com.airlock.iam.base.api.domain.model.user.UserId;
import com.airlock.iam.common.api.domain.model.store.user.UserStore;
import com.airlock.iam.common.api.domain.model.user.PersistentUser;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Stream;

public final class UserDataServiceImpl implements UserDataService {
   private final Provider<UserStore> userStore;
   private final Provider<IdentityProvidingByUserDataServiceImpl.IdentityProvidingByUserDataServiceSettings> settings;

   @Inject
   public UserDataServiceImpl(
      Provider<UserStore> userStore, Provider<IdentityProvidingByUserDataServiceImpl.IdentityProvidingByUserDataServiceSettings> settings
   ) {
      this.userStore = userStore;
      this.settings = settings;
   }

   @Override
   public List<UserId> findUsersByUserData(Map<String, String> userData) {
      try (Stream<String> resultStream = ((UserStore)this.userStore.get())
            .find()
            .whereAllOf(this.createRestrictions(userData))
            .select(((UserStore)this.userStore.get()).schema().identity().selector())
            .stream()) {
         return resultStream.map(UserId::userId).toList();
      }
   }

   private List<Restriction> createRestrictions(Map<String, String> userData) {
      return userData.entrySet().stream().map(this::createRestriction).toList();
   }

   private Restriction createRestriction(Entry<String, String> entry) {
      StringField<PersistentUser> field = ((UserStore)this.userStore.get()).schema().customFields().string(entry.getKey());
      return ((IdentityProvidingByUserDataServiceImpl.IdentityProvidingByUserDataServiceSettings)this.settings.get()).ignoreCase()
         ? field.equalIgnoreCase(entry.getValue())
         : field.equal(entry.getValue());
   }
}
