package com.airlock.iam.admin.application.service.settings.provider;

import com.airlock.iam.admin.application.configuration.tokens.TokensConfiguration;
import com.airlock.iam.admin.application.configuration.tokens.vasco.VascoCrontoTokenManager;
import com.airlock.iam.admin.application.configuration.tokens.vasco.VascoOtpTokenManager;
import com.airlock.iam.admin.application.configuration.vasco.VascoOtpTokenControllerConfig;
import com.airlock.iam.admin.application.service.SettingsProvider;
import com.airlock.iam.admin.application.service.settings.Settings;
import com.airlock.iam.admin.application.service.settings.TokenManagerSettings;
import com.airlock.iam.admin.application.system.AdminappPage;
import com.airlock.iam.admin.domain.model.token.TokenController;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class TokenManagerSettingsProvider implements SettingsProvider {
   private final Optional<TokensConfiguration> config;
   private final List<TokenController> tokenControllers;

   @Override
   public AdminappPage page() {
      return AdminappPage.TOKEN_LIST;
   }

   @Override
   public Optional<Settings> getSettings() {
      return this.config.isEmpty()
         ? Optional.empty()
         : Optional.of(
            TokenManagerSettings.builder()
               .vascoOtp(this.getVascoOtpTokenManagerSettings(this.config.get()))
               .vascoCronto(this.getVascoCrontoTokenManagerSettings(this.config.get()))
               .build()
         );
   }

   private Map<String, Object> getVascoCrontoTokenManagerSettings(TokensConfiguration tokenConfig) {
      return tokenConfig.getTokenManagers()
         .stream()
         .filter(VascoCrontoTokenManager.class::isInstance)
         .findAny()
         .map(VascoCrontoTokenManager.class::cast)
         .map(crontoManager -> Map.of("importSoftwareVector", crontoManager.isSoftwareVectorImportEnabled()))
         .orElse(null);
   }

   private Map<String, Object> getVascoOtpTokenManagerSettings(TokensConfiguration tokenConfig) {
      return tokenConfig.getTokenManagers().stream().filter(VascoOtpTokenManager.class::isInstance).findAny().map(m -> this.vascoOtpSettings()).orElse(null);
   }

   private Map<String, Object> vascoOtpSettings() {
      return this.tokenControllers
         .stream()
         .filter(VascoOtpTokenControllerConfig.class::isInstance)
         .findFirst()
         .map(VascoOtpTokenControllerConfig.class::cast)
         .flatMap(c -> Optional.ofNullable(c.getAdditionalInfoResourceKeyPrefix()))
         .map(prefix -> Map.of("additionalInformationResourceKeyPrefix", prefix))
         .orElseGet(Collections::emptyMap);
   }

   @SuppressFBWarnings(justification = "generated code")
   public TokenManagerSettingsProvider(Optional<TokensConfiguration> config, List<TokenController> tokenControllers) {
      this.config = config;
      this.tokenControllers = tokenControllers;
   }
}
