package com.airlock.iam.authentication.domain.model.idpropagation;

import com.airlock.iam.base.api.domain.model.exception.FailureException;
import com.airlock.iam.common.api.domain.model.user.UserIdentity;
import com.airlock.iam.common.api.domain.model.user.UsernameToPropagate;
import com.airlock.iam.common.domain.model.auth.idpropagation.WafCredential;
import com.airlock.iam.flow.api.domain.model.flow.ApplicationId;
import com.airlock.iam.login.domain.model.location.propagate.TargetURIResolver;
import com.airlock.iam.login.domain.model.targetapp.WafCredentialProvider;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Collection;
import java.util.List;
import java.util.Optional;

public final class CurrentTargetApplication {
   private final Provider<ApplicationId> applicationId;
   private final Provider<Optional<UsernameToPropagate>> usernameToUsernameProvider;
   private final Provider<List<FlowIdentityPropagator>> idPropagators;
   private final Provider<List<WafCredentialProvider>> wafCredentialProviders;
   private final Provider<Optional<TargetURIResolver>> targetOnFlowCompletion;

   @Inject
   public CurrentTargetApplication(
      Provider<ApplicationId> applicationId,
      Provider<Optional<UsernameToPropagate>> usernameToUsernameProvider,
      Provider<List<FlowIdentityPropagator>> idPropagators,
      Provider<List<WafCredentialProvider>> wafCredentialProviders,
      Provider<Optional<TargetURIResolver>> targetOnFlowCompletion
   ) {
      this.applicationId = applicationId;
      this.usernameToUsernameProvider = usernameToUsernameProvider;
      this.idPropagators = idPropagators;
      this.wafCredentialProviders = wafCredentialProviders;
      this.targetOnFlowCompletion = targetOnFlowCompletion;
   }

   public void propagateIdentity(UserIdentity userId) {
      UsernameToPropagate usernameToPropagate = (UsernameToPropagate)((Optional)this.usernameToUsernameProvider.get())
         .orElseThrow(() -> new FailureException("Username to propagate was empty."));
      ((List)this.idPropagators.get())
         .stream()
         .filter(FlowIdentityPropagator::isConditionFulfilled)
         .forEach(p -> p.propagateIdentity(userId, usernameToPropagate));
   }

   public List<WafCredential> getWafCredentials() {
      return ((List)this.wafCredentialProviders.get()).stream().map(WafCredentialProvider::getCredentials).flatMap(Collection::stream).toList();
   }

   public Optional<TargetURIResolver> getTargetOnFlowCompletion() {
      return (Optional<TargetURIResolver>)this.targetOnFlowCompletion.get();
   }

   public ApplicationId getApplicationId() {
      return (ApplicationId)this.applicationId.get();
   }
}
