package com.airlock.iam.saml2.application.configuration.assertion.attribute;

import com.airlock.iam.plugin.api.annotation.config.ConfigurationValidator;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.airlock.iam.plugin.api.annotation.license.PluginLicenseRestriction;
import com.airlock.iam.plugin.api.annotation.property.StringProperty;
import com.airlock.iam.plugin.api.config.ConfigurationContext;
import com.airlock.iam.plugin.api.config.ConfigurationEnvironment;
import com.airlock.iam.plugin.api.config.Environment;
import com.airlock.iam.plugin.api.config.PluginConfiguration;
import com.airlock.iam.plugin.api.exception.ConfigurationException;
import com.airlock.iam.plugin.framework.application.configuration.validator.FastDateFormatPatternValidator;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Locale;
import java.util.Optional;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.commons.lang3.time.TimeZones;

@Plugin(description = "A SAML 2.0 attribute containing the authentication instant.", displayName = "Authentication Instant SAML 2.0 Attribute")
@PluginLicenseRestriction(moduleAffiliation = "SamlIdp")
public class AuthenticationInstantAttributeConfig extends SamlIdpAttributeConfigWithNameFormat implements SamlFlowIdpAttributeConfig {
   @StringProperty(
      displayName = "Attribute Name",
      description = "The name of the attribute to add to the assertion.",
      exampleValues = "AuthInstant",
      optional = false
   )
   private String samlAttributeName;
   @StringProperty(
      description = "<p>\nIf this property is set, the SAML 2.0 attribute will contain the authentication instant formatted using the\nconfigured date and time format. The format is interpreted as specified in the <code>java.text.SimpleDateFormat</code>\n<a href=\"https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/text/SimpleDateFormat.html\" target=\"_blank\">documentation</a>.\nNote that the output time zone is fixed to GMT.\n</p>\n<p>\nIf this property is not set, the attribute value will contain the authentication instant as a Unix timestamp\n(i.e. milliseconds since epoch).\n</p>",
      optional = true,
      exampleValues = {"yyyy-MM-dd'T'HH:mm:ss'Z'", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "yyyy-MM-dd HH:mm:ss"}
   )
   private String dateAndTimeFormat;
   private static final String DATE_AND_TIME_FORMAT_PROPERTY = "dateAndTimeFormat";

   @ConfigurationValidator
   public static void validateConfiguredTimezoneAndDateFormat(
      PluginConfiguration config, ConfigurationEnvironment env, ConfigurationContext context, Environment validationEnvironment
   ) throws ConfigurationException {
      FastDateFormatPatternValidator.validateFastDateFormatPattern(config, "dateAndTimeFormat", env, context);
   }

   public AuthenticationInstantAttributeConfig(String samlAttributeName, String nameFormat, String dateAndTimeFormat) {
      super(nameFormat);
      this.samlAttributeName = samlAttributeName;
      this.dateAndTimeFormat = dateAndTimeFormat;
   }

   public Optional<FastDateFormat> getDateAndTimeFormat() {
      return Optional.ofNullable(this.dateAndTimeFormat).map(AuthenticationInstantAttributeConfig::getDateAndTimeFormat);
   }

   private static FastDateFormat getDateAndTimeFormat(String pattern) {
      return FastDateFormat.getInstance(pattern, TimeZones.GMT, Locale.US);
   }

   @Override
   public String getSamlAttributeName() {
      return this.samlAttributeName;
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public static class AuthenticationInstantAttributeConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private String samlAttributeName;
      @SuppressFBWarnings(justification = "generated code")
      private String nameFormat;
      @SuppressFBWarnings(justification = "generated code")
      private String dateAndTimeFormat;

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

      @SuppressFBWarnings(justification = "generated code")
      public AuthenticationInstantAttributeConfig.AuthenticationInstantAttributeConfigBuilder samlAttributeName(String samlAttributeName) {
         this.samlAttributeName = samlAttributeName;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AuthenticationInstantAttributeConfig.AuthenticationInstantAttributeConfigBuilder nameFormat(String nameFormat) {
         this.nameFormat = nameFormat;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AuthenticationInstantAttributeConfig.AuthenticationInstantAttributeConfigBuilder dateAndTimeFormat(String dateAndTimeFormat) {
         this.dateAndTimeFormat = dateAndTimeFormat;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AuthenticationInstantAttributeConfig build() {
         return new AuthenticationInstantAttributeConfig(this.samlAttributeName, this.nameFormat, this.dateAndTimeFormat);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "AuthenticationInstantAttributeConfig.AuthenticationInstantAttributeConfigBuilder(samlAttributeName="
            + this.samlAttributeName
            + ", nameFormat="
            + this.nameFormat
            + ", dateAndTimeFormat="
            + this.dateAndTimeFormat
            + ")";
      }
   }
}
