package com.airlock.iam.oauth2.domain.service;

import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.flow.api.domain.model.flow.ApplicationId;
import com.airlock.iam.oauth2.api.domain.model.OAuth2ClientId;
import com.airlock.iam.oauth2.domain.model.acr.AcrToApplicationId;
import com.airlock.iam.oauth2.domain.model.acr.OpenIdConnectAcrValue;
import com.airlock.iam.oauth2.domain.model.settings.OAuth2ApplicationFlowSelectionSettings;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.inject.Inject;
import java.util.List;
import java.util.function.Supplier;

public final class OAuth2ApplicationFlowSelection {
   private static final ELogger LOG = ELoggerFactory.getLogger(OAuth2ApplicationFlowSelection.class);
   private final OAuth2ApplicationFlowSelectionSettings settings;
   private final Supplier<ApplicationId> defaultApplicationIdProvider;

   @Inject
   public OAuth2ApplicationFlowSelection(OAuth2ApplicationFlowSelectionSettings settings, Supplier<ApplicationId> defaultApplicationIdProvider) {
      this.settings = settings;
      this.defaultApplicationIdProvider = defaultApplicationIdProvider;
   }

   public ApplicationId select(List<OpenIdConnectAcrValue> requestedAcrValues, OAuth2ClientId clientId) {
      return this.settings
         .mapRequestedAcrToAppId(requestedAcrValues, clientId)
         .stream()
         .findFirst()
         .map(AcrToApplicationId::getAuthenticationFlowId)
         .or(() -> this.settings.getTargetFlowId(clientId))
         .orElseGet(this.defaultApplicationIdProvider);
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public static class OAuth2ApplicationFlowSelectionBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private OAuth2ApplicationFlowSelectionSettings settings;
      @SuppressFBWarnings(justification = "generated code")
      private Supplier<ApplicationId> defaultApplicationIdProvider;

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

      @SuppressFBWarnings(justification = "generated code")
      public OAuth2ApplicationFlowSelection.OAuth2ApplicationFlowSelectionBuilder settings(OAuth2ApplicationFlowSelectionSettings settings) {
         this.settings = settings;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public OAuth2ApplicationFlowSelection.OAuth2ApplicationFlowSelectionBuilder defaultApplicationIdProvider(
         Supplier<ApplicationId> defaultApplicationIdProvider
      ) {
         this.defaultApplicationIdProvider = defaultApplicationIdProvider;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public OAuth2ApplicationFlowSelection build() {
         return new OAuth2ApplicationFlowSelection(this.settings, this.defaultApplicationIdProvider);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "OAuth2ApplicationFlowSelection.OAuth2ApplicationFlowSelectionBuilder(settings="
            + this.settings
            + ", defaultApplicationIdProvider="
            + this.defaultApplicationIdProvider
            + ")";
      }
   }
}
