package com.airlock.iam.saml2.infrastructure.service.idp;

import com.airlock.iam.login.application.configuration.targetapp.ApplicationIdConfig;
import com.airlock.iam.saml2.application.configuration.Saml2FlowIdpConfig;
import com.airlock.iam.saml2.application.configuration.Saml2RequestedAuthnContextToApplicationIdConfig;
import com.airlock.iam.saml2.application.configuration.Saml2ServiceProviderAccessConfig;
import com.airlock.iam.saml2.domain.model.sp.Saml2SpEntityId;
import com.airlock.iam.saml2.domain.service.Saml2IdpFlowConfigService;
import com.sun.identity.saml2.protocol.AuthnRequest;
import com.sun.identity.saml2.protocol.RequestedAuthnContext;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.List;
import java.util.Optional;

public class Saml2IdpFlowConfigServiceImpl implements Saml2IdpFlowConfigService {
   private final Provider<Saml2FlowIdpConfig> idpFlowConfig;

   @Inject
   public Saml2IdpFlowConfigServiceImpl(Provider<Saml2FlowIdpConfig> idpFlowConfig) {
      this.idpFlowConfig = idpFlowConfig;
   }

   @Override
   public Optional<Saml2ServiceProviderAccessConfig> getSpAccessConfigBySpIssuer(Saml2SpEntityId issuer) {
      return ((Saml2FlowIdpConfig)this.idpFlowConfig.get()).getServiceProvider(issuer.value());
   }

   @Override
   public Optional<ApplicationIdConfig> getRequestedAuthnContextAppIdConfig(AuthnRequest authnRequest, Saml2ServiceProviderAccessConfig spAccessConfig) {
      RequestedAuthnContext requestedAuthnContext = authnRequest.getRequestedAuthnContext();
      if (requestedAuthnContext != null) {
         List<String> requestedRefs = requestedAuthnContext.getAuthnContextClassRef();
         if (requestedRefs != null && !requestedRefs.isEmpty()) {
            Optional<Saml2RequestedAuthnContextToApplicationIdConfig> authnContextToApplicationIdConfig = this.getApplicationIdByAuthnContextClassRef(
               requestedRefs, spAccessConfig
            );
            if (authnContextToApplicationIdConfig.isPresent()) {
               return Optional.of(authnContextToApplicationIdConfig.get().getFlowApplicationId());
            }
         }
      }

      return Optional.empty();
   }

   private Optional<Saml2RequestedAuthnContextToApplicationIdConfig> getApplicationIdByAuthnContextClassRef(
      List<String> requestedRefs, Saml2ServiceProviderAccessConfig spAccessConfig
   ) {
      return spAccessConfig.getRequestedAuthnContextToFlowAppId()
         .stream()
         .filter(config -> requestedRefs.contains(config.getRequestedAuthnContextValue()))
         .findFirst();
   }

   @SuppressFBWarnings(justification = "generated code")
   public static Saml2IdpFlowConfigServiceImpl.Saml2IdpFlowConfigServiceImplBuilder builder() {
      return new Saml2IdpFlowConfigServiceImpl.Saml2IdpFlowConfigServiceImplBuilder();
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class Saml2IdpFlowConfigServiceImplBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private Provider<Saml2FlowIdpConfig> idpFlowConfig;

      @SuppressFBWarnings(justification = "generated code")
      Saml2IdpFlowConfigServiceImplBuilder() {
      }

      @SuppressFBWarnings(justification = "generated code")
      public Saml2IdpFlowConfigServiceImpl.Saml2IdpFlowConfigServiceImplBuilder idpFlowConfig(Provider<Saml2FlowIdpConfig> idpFlowConfig) {
         this.idpFlowConfig = idpFlowConfig;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public Saml2IdpFlowConfigServiceImpl build() {
         return new Saml2IdpFlowConfigServiceImpl(this.idpFlowConfig);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "Saml2IdpFlowConfigServiceImpl.Saml2IdpFlowConfigServiceImplBuilder(idpFlowConfig=" + this.idpFlowConfig + ")";
      }
   }
}
