package com.airlock.iam.admin.application.configuration;

import com.airlock.iam.admin.application.configuration.tokens.vasco.VascoOtpTokenManager;
import com.airlock.iam.admin.application.configuration.vasco.VascoOtpTokenControllerConfig;
import com.airlock.iam.base.misc.log.LogUtil;
import com.airlock.iam.plugin.api.config.ConfigurationContext;
import com.airlock.iam.plugin.api.config.ConfigurationEnvironment;
import com.airlock.iam.plugin.api.config.PluginConfiguration;
import com.airlock.iam.plugin.api.exception.InitializeException;
import com.airlock.iam.plugin.api.exception.PropertyConfigurationException;
import com.airlock.iam.plugin.api.exception.PropertyTypeMismatchException;
import com.airlock.iam.plugin.api.valuereader.PluginListPropertyValueReader;
import com.airlock.iam.plugin.api.valuereader.PluginPropertyValueReader;
import com.airlock.iam.plugin.api.valuereader.StringPropertyValueReader;
import java.util.List;

public final class AdminappConfigValidator {
   private AdminappConfigValidator() {
   }

   public static void checkCustomLoginUrl(PluginConfiguration config, ConfigurationEnvironment env, ConfigurationContext context) throws PropertyConfigurationException {
      String customLoginUrl = StringPropertyValueReader.effectiveStringConfigValue(config, "customLoginUrl", env, context);
      if (customLoginUrl != null) {
         if (customLoginUrl.startsWith("ui/")) {
            throw new PropertyConfigurationException(
               config,
               env,
               context,
               "The " + LogUtil.quote("Custom Login URL") + " must not be relative to the Adminapp's UI path (ui/..)",
               new String[]{"customLoginUrl"}
            );
         }
      }
   }

   public static void checkIfVascoOtpTokenManagerRequired(PluginConfiguration config, ConfigurationEnvironment env, ConfigurationContext context) throws PropertyConfigurationException {
      PluginConfiguration usersConfig = PluginPropertyValueReader.effectivePluginPropertyValue(config, "users", env, context);
      if (usersConfig != null) {
         List<PluginConfiguration> tokenControllersConfig = PluginListPropertyValueReader.effectivePluginListPropertyValue(
            usersConfig, "authenticationTokens", env, context
         );
         boolean hasVascoOtpTokenController = tokenControllersConfig.stream().anyMatch(pc -> VascoOtpTokenControllerConfig.class.equals(getPluginClass(pc)));
         if (hasVascoOtpTokenController) {
            PluginConfiguration tokensConfig = PluginPropertyValueReader.effectivePluginPropertyValue(config, "tokens", env, context);
            boolean hasVascoOtpTokenManager = hasVascoOtpTokenManager(tokensConfig, env, context);
            if (!hasVascoOtpTokenManager) {
               throw new PropertyConfigurationException(
                  config,
                  env,
                  context,
                  "It is required to configure a "
                     + LogUtil.quote("Vasco OTP Token Manager")
                     + " when a "
                     + LogUtil.quote("Vasco OTP Token Controller")
                     + " is configured",
                  new String[]{"tokens"}
               );
            }
         }
      }
   }

   private static boolean hasVascoOtpTokenManager(PluginConfiguration tokensConfig, ConfigurationEnvironment env, ConfigurationContext context) throws PropertyTypeMismatchException {
      if (tokensConfig == null) {
         return false;
      }

      List<PluginConfiguration> tokenManagers = PluginListPropertyValueReader.effectivePluginListPropertyValue(tokensConfig, "tokenManagers", env, context);
      return tokenManagers.stream().anyMatch(pc -> VascoOtpTokenManager.class.equals(getPluginClass(pc)));
   }

   private static Class<?> getPluginClass(PluginConfiguration pc) {
      try {
         return pc.getPluginClass();
      } catch (InitializeException e) {
         return null;
      }
   }
}
