package com.airlock.iam.common.application.configuration.valueprovider;

import com.airlock.iam.common.api.application.configuration.valueprovider.DateAndTimeValueProviderConfig;
import com.airlock.iam.common.api.application.configuration.valueprovider.StringValueProviderConfig;
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.property.PluginProperty;
import com.airlock.iam.plugin.api.annotation.property.StringListProperty;
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.List;
import org.apache.commons.lang3.time.FastDateFormat;

@Plugin(description = "Parses and provides a date and time value from a string.", displayName = "Date-Time From String Value Provider")
public class DateAndTimeFromStringValueProviderConfig implements DateAndTimeValueProviderConfig {
   @PluginProperty(
      description = "The string to convert to a date.\n<p>Examples of strings supported by the default formats:\n<ul>\n\t<li>2011-12-03T10:15:30+01:00</li>\n\t<li>2011-12-03T10:15:30+0100</li>\n\t<li>2011-12-03T10:15:30+01</li>\n\t<li>2011-12-03T10:15:30.000+01:00</li>\n\t<li>2011-12-03T10:15:30.000+0100</li>\n\t<li>2011-12-03T10:15:30.000+01</li>\n\t<li>2011-12-03T10:15:30Z</li>\n\t<li>2011-12-03T10:15:30.000Z</li>\n</ul></p>",
      optional = false,
      displayName = "String Value Provider"
   )
   private StringValueProviderConfig stringValueProvider;
   private static final String STRING_VALUE_PROVIDER_DISPLAY_NAME = "String Value Provider";
   @StringListProperty(
      displayName = "Formats",
      description = "<p>The date and time formats used to parse the value provided by String Value Provider.</p><p>The format is interpreted as specified in the <code>java.text.SimpleDateFormat</code> <a href=\"https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/text/SimpleDateFormat.html\" target=\"_blank\">documentation</a>.</p><p>Each format is tried sequentially, until a format matches. One of the formats must match, else an exception is thrown.</p>",
      optional = true,
      defaultValue = {"yyyy-MM-dd'T'HH:mm:ssX", "yyyy-MM-dd'T'HH:mm:ss.SSSX"},
      exampleElements = {"yyyy-MM-dd'T'HH:mm:ssZ", "dd.MM.yyyy", "MM/dd/yyyy", "MMM dd, YYYY 'at' HH:mm z"}
   )
   private List<String> formats;
   private static final String FORMATS_PROPERTY = "formats";
   private static final String FORMATS_DISPLAY_NAME = "Formats";

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

   public StringValueProviderConfig getValueProviderConfig() {
      return this.stringValueProvider;
   }

   public List<FastDateFormat> getFormats() {
      return this.formats.stream().<FastDateFormat>map(FastDateFormat::getInstance).toList();
   }

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

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

   @SuppressFBWarnings(justification = "generated code")
   public DateAndTimeFromStringValueProviderConfig(StringValueProviderConfig stringValueProvider, List<String> formats) {
      this.stringValueProvider = stringValueProvider;
      this.formats = formats;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class DateAndTimeFromStringValueProviderConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private StringValueProviderConfig stringValueProvider;
      @SuppressFBWarnings(justification = "generated code")
      private List<String> formats;

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

      @SuppressFBWarnings(justification = "generated code")
      public DateAndTimeFromStringValueProviderConfig.DateAndTimeFromStringValueProviderConfigBuilder stringValueProvider(
         StringValueProviderConfig stringValueProvider
      ) {
         this.stringValueProvider = stringValueProvider;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DateAndTimeFromStringValueProviderConfig.DateAndTimeFromStringValueProviderConfigBuilder formats(List<String> formats) {
         this.formats = formats;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public DateAndTimeFromStringValueProviderConfig build() {
         return new DateAndTimeFromStringValueProviderConfig(this.stringValueProvider, this.formats);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "DateAndTimeFromStringValueProviderConfig.DateAndTimeFromStringValueProviderConfigBuilder(stringValueProvider="
            + this.stringValueProvider
            + ", formats="
            + this.formats
            + ")";
      }
   }
}
