package com.airlock.iam.login.application.configuration.event;

import com.airlock.iam.common.api.application.configuration.valueprovider.StringValueProviderConfig;
import com.airlock.iam.common.application.configuration.event.LoginappSubscribedEventConfig;
import com.airlock.iam.common.application.configuration.mtan.BasicMtanSettings;
import com.airlock.iam.common.application.configuration.sms.PhoneNumbersProviderConfig;
import com.airlock.iam.flow.api.application.configuration.valueprovider.ValueMapProviderConfig;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.airlock.iam.plugin.api.annotation.property.PluginListProperty;
import com.airlock.iam.plugin.api.annotation.property.PluginProperty;
import com.airlock.iam.plugin.api.annotation.property.StringProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

@Plugin(description = "An event subscriber that sends an SMS to notify a user.", displayName = "SMS Event Subscriber (Loginapp)")
public final class LoginappSmsEventSubscriberConfig extends LoginappGeneralEventSubscriberConfig {
   @PluginProperty(description = "Settings to send a SMS to the notified user.", displayName = "SMS Settings", optional = false)
   private BasicMtanSettings smsSettings;
   @PluginListProperty(description = "Provides the phone numbers to which the notification will be sent.", optional = false)
   private List<PhoneNumbersProviderConfig> phoneNumberProviders;
   @StringProperty(
      description = "The resource key under which the localized template for the sms message can be found. The following syntax can be used to include data in the template. <ul><li><tt>${valueMapKey}</tt> for the value of <tt>valueMapKey</tt> provided by any of the configured Value Map Providers.</li><li><tt>${event.createdAt,date,format}</tt> to include the date/time at which the event was created, where \"format\" is a date pattern like \"yyyy-MM-dd HH:mm:ss\".</li></ul>Depending on the event and on the conditions in which the event originated, the following variables may also be available: <ul><li><tt>event.createdAt</tt></li><li><tt>event.data.airlock2FAAccountId</tt></li><li><tt>event.data.airlock2FADeviceId</tt></li><li><tt>event.data.activeAuthenticationMethod</tt></li><li><tt>event.data.authenticationMethods</tt></li><li><tt>event.data.browser</tt></li><li><tt>event.data.city</tt></li><li><tt>event.data.contextDataChanged.%s.newValue</tt> (where \"%s\" is replaced by the context-data field name).</li><li><tt>event.data.contextDataChanged.%s.oldValue</tt> (where \"%s\" is replaced by the context-data field name).</li><li><tt>event.data.countryCode</tt></li><li><tt>event.data.crontoDeviceId</tt></li><li><tt>event.data.device</tt></li><li><tt>event.data.deviceTokenId</tt></li><li><tt>event.data.fidoCredentialId</tt></li><li><tt>event.data.fidoPublicKeyCredentialId</tt></li><li><tt>event.data.oauth2.authorizationServerId</tt></li><li><tt>event.data.fidoRelyingPartyId</tt></li><li><tt>event.data.lockReason</tt></li><li><tt>event.data.mtanNewPhoneNumber</tt></li><li><tt>event.data.mtanNumberId</tt></li><li><tt>event.data.mtanOldPhoneNumber</tt></li><li><tt>event.data.newEmailAddress</tt></li><li><tt>event.data.oauth2.acceptedScopes</tt></li><li><tt>event.data.oauth2.alwaysGrantedScopes</tt></li><li><tt>event.data.oauth2.clientId</tt></li><li><tt>event.data.oauth2.deniedScopes</tt></li><li><tt>event.data.oldEmailAddress</tt></li><li><tt>event.data.operatingSystem</tt></li><li><tt>event.data.previousAuthenticationMethod</tt></li><li><tt>event.data.stepResult.attributes.&lt;attribute-name&gt;</tt> (where &lt;attribute-name&gt ist the name of the additional attribute, could be nested.)</li><li><tt>event.data.stepResult.errorCode</tt></li><li><tt>event.data.stepResult.nextAction</tt></li><li><tt>event.data.stepResult.type</tt></li><li><tt>event.data.userId</tt></li><li><tt>event.id</tt></li><li><tt>event.metadata.requestIp</tt></li><li><tt>event.metadata.userAgent</tt></li><li><tt>event.source.applicationId</tt></li><li><tt>event.source.configurationContext</tt></li><li><tt>event.source.flowId</tt></li><li><tt>event.source.stepId</tt></li></ul>Variables that are not defined are replaced by an empty string. The Airlock IAM documentation provides further information about the availability of specific variables.",
      optional = true,
      defaultValue = "sms.notification.message"
   )
   private String messageResourceKey;
   @PluginProperty(
      description = "A String Value Provider which provides the language of the message. It is recommended to use a context data field and not the display language, as latter could be misused by an attacker to confuse the victim with an unknown language.",
      optional = false
   )
   private StringValueProviderConfig language;

   public LoginappSmsEventSubscriberConfig(
      LoginappSubscribedEventConfig event,
      List<ValueMapProviderConfig> valueMapProviders,
      BasicMtanSettings smsSettings,
      List<PhoneNumbersProviderConfig> phoneNumberProviders,
      String messageResourceKey,
      StringValueProviderConfig language
   ) {
      super(event, valueMapProviders);
      this.smsSettings = smsSettings;
      this.phoneNumberProviders = phoneNumberProviders;
      this.messageResourceKey = messageResourceKey;
      this.language = language;
   }

   public BasicMtanSettings getSmsSettings() {
      return this.smsSettings;
   }

   public List<PhoneNumbersProviderConfig> getPhoneNumberProviders() {
      return this.phoneNumberProviders;
   }

   public String getMessageResourceKey() {
      return this.messageResourceKey;
   }

   public StringValueProviderConfig getLanguage() {
      return this.language;
   }

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

   @SuppressFBWarnings(justification = "generated code")
   public LoginappSmsEventSubscriberConfig() {
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class LoginappSmsEventSubscriberConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private LoginappSubscribedEventConfig event;
      @SuppressFBWarnings(justification = "generated code")
      private List<ValueMapProviderConfig> valueMapProviders;
      @SuppressFBWarnings(justification = "generated code")
      private BasicMtanSettings smsSettings;
      @SuppressFBWarnings(justification = "generated code")
      private ArrayList<PhoneNumbersProviderConfig> phoneNumberProviders;
      @SuppressFBWarnings(justification = "generated code")
      private String messageResourceKey;
      @SuppressFBWarnings(justification = "generated code")
      private StringValueProviderConfig language;

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

      @SuppressFBWarnings(justification = "generated code")
      public LoginappSmsEventSubscriberConfig.LoginappSmsEventSubscriberConfigBuilder event(LoginappSubscribedEventConfig event) {
         this.event = event;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public LoginappSmsEventSubscriberConfig.LoginappSmsEventSubscriberConfigBuilder valueMapProviders(List<ValueMapProviderConfig> valueMapProviders) {
         this.valueMapProviders = valueMapProviders;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public LoginappSmsEventSubscriberConfig.LoginappSmsEventSubscriberConfigBuilder smsSettings(BasicMtanSettings smsSettings) {
         this.smsSettings = smsSettings;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public LoginappSmsEventSubscriberConfig.LoginappSmsEventSubscriberConfigBuilder phoneNumberProvider(PhoneNumbersProviderConfig phoneNumberProvider) {
         if (this.phoneNumberProviders == null) {
            this.phoneNumberProviders = new ArrayList<>();
         }

         this.phoneNumberProviders.add(phoneNumberProvider);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public LoginappSmsEventSubscriberConfig.LoginappSmsEventSubscriberConfigBuilder phoneNumberProviders(
         Collection<? extends PhoneNumbersProviderConfig> phoneNumberProviders
      ) {
         if (phoneNumberProviders == null) {
            throw new NullPointerException("phoneNumberProviders cannot be null");
         }

         if (this.phoneNumberProviders == null) {
            this.phoneNumberProviders = new ArrayList<>();
         }

         this.phoneNumberProviders.addAll(phoneNumberProviders);
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public LoginappSmsEventSubscriberConfig.LoginappSmsEventSubscriberConfigBuilder clearPhoneNumberProviders() {
         if (this.phoneNumberProviders != null) {
            this.phoneNumberProviders.clear();
         }

         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public LoginappSmsEventSubscriberConfig.LoginappSmsEventSubscriberConfigBuilder messageResourceKey(String messageResourceKey) {
         this.messageResourceKey = messageResourceKey;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public LoginappSmsEventSubscriberConfig.LoginappSmsEventSubscriberConfigBuilder language(StringValueProviderConfig language) {
         this.language = language;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public LoginappSmsEventSubscriberConfig build() {
         return new LoginappSmsEventSubscriberConfig(
            this.event, this.valueMapProviders, this.smsSettings, switch (this.phoneNumberProviders == null ? 0 : this.phoneNumberProviders.size()) {
               case 0 -> Collections.emptyList();
               case 1 -> Collections.singletonList(this.phoneNumberProviders.get(0));
               default -> Collections.unmodifiableList(new ArrayList<>(this.phoneNumberProviders));
            }, this.messageResourceKey, this.language
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "LoginappSmsEventSubscriberConfig.LoginappSmsEventSubscriberConfigBuilder(event="
            + this.event
            + ", valueMapProviders="
            + this.valueMapProviders
            + ", smsSettings="
            + this.smsSettings
            + ", phoneNumberProviders="
            + this.phoneNumberProviders
            + ", messageResourceKey="
            + this.messageResourceKey
            + ", language="
            + this.language
            + ")";
      }
   }
}
