package com.airlock.iam.flow.shared.domain.model.condition;

import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.common.domain.model.user.PrincipalInfo;
import com.airlock.iam.factor.domain.model.fido.FidoCredentialRepository;
import com.airlock.iam.factor.domain.model.fido.FidoUserRepository;
import com.airlock.iam.fido.api.domain.model.FidoRelyingPartyId;
import com.airlock.iam.flow.api.domain.model.step.FlowCondition;
import com.airlock.iam.flow.shared.application.configuration.step.FidoCredentialConditionConfig;
import jakarta.inject.Inject;
import jakarta.inject.Provider;

@LogicForConfig(FidoCredentialConditionConfig.class)
public class FidoCredentialCondition implements FlowCondition {
   private final Provider<FidoUserRepository> userRepository;
   private final Provider<FidoCredentialRepository> credentialRepository;
   private final Provider<PrincipalInfo> user;
   private final FidoRelyingPartyId relyingPartyId;

   @Inject
   public FidoCredentialCondition(
      Provider<FidoUserRepository> userRepository,
      Provider<FidoCredentialRepository> credentialRepository,
      Provider<PrincipalInfo> user,
      FidoRelyingPartyId relyingPartyId
   ) {
      this.userRepository = userRepository;
      this.credentialRepository = credentialRepository;
      this.user = user;
      this.relyingPartyId = relyingPartyId;
   }

   @Override
   public boolean isFulfilled() {
      return ((PrincipalInfo)this.user.get())
         .getKnownIdentity()
         .flatMap(identity -> ((FidoUserRepository)this.userRepository.get()).findBy(this.relyingPartyId, identity.id()))
         .map(fidoUser -> ((FidoCredentialRepository)this.credentialRepository.get()).credentialIdsAndTransportsUsableBy(fidoUser))
         .map(credentials -> !credentials.isEmpty())
         .orElse(false);
   }

   @Override
   public String displayName() {
      return "Has FIDO Credential";
   }
}
