content: package org.ays.auth.config;
  
  import lombok.Getter;
  import lombok.extern.slf4j.Slf4j;
  import org.ays.auth.model.enums.AysConfigurationParameter;
  import org.ays.auth.util.AysKeyConverter;
  import org.ays.parameter.model.AysParameter;
  import org.ays.parameter.port.AysParameterReadPort;
  import org.springframework.context.annotation.Configuration;
  
  import java.security.PrivateKey;
  import java.security.PublicKey;
  import java.util.List;
  import java.util.Optional;
  
  /**
   * Configuration class for AYS application parameters.
   * <p>
   * This class reads and initializes configuration parameters from the underlying data source using the
   * {@link AysParameterReadPort}. It retrieves values such as the issuer, expiration durations, and cryptographic keys,
   * and falls back to default values when necessary.
   * </p>
   */
  @Slf4j
  @Getter
  @Configuration
  public class AysApplicationConfigurationParameter {
  
      /**
       * The issuer value to be used in JWTs generated by the application.
       */
      private final String tokenIssuer;
      /**
       * The private key used for token signing.
       * This key is converted from an encrypted PEM format using {@link AysKeyConverter}.
       */
      private final PrivateKey tokenPrivateKey;
      /**
       * The public key used for token verification.
       * This key is converted from an encrypted PEM format using {@link AysKeyConverter}.
       */
      private final PublicKey tokenPublicKey;
      /**
       * The number of minutes until access tokens expire.
       * Derived from configuration parameters or defaults if not provided.
       */
      private final Integer accessTokenExpireMinute;
      /**
       * The number of minutes until refresh tokens expire.
       * Derived from configuration parameters or defaults if not provided.
       */
      private final Integer refreshTokenExpireMinute;
      /**
       * The frontend URL to use for email verification, password reset, and other links.
       * Derived from configuration parameters or defaults if not provided.
       */
      private final String feUrl;
  
  
      /**
       * Constructs a new {@code AysApplicationConfigurationParameter} instance.
       * <p>
       * This constructor retrieves the necessary configuration parameters using the provided
       * {@link AysParameterReadPort}. It reads values such as the issuer, expiration durations,
       * and cryptographic keys, applying default values when parameters are missing.
       * </p>
       *
       * @param parameterReadPort the {@link AysParameterReadPort} instance used for retrieving configuration parameters
       */
      public AysApplicationConfigurationParameter(AysParameterReadPort parameterReadPort) {
  
          log.info("Application Configuration Parameters reading...");
  
          final List<AysParameter> configurationParameters = parameterReadPort.findAll();
  
          this.tokenIssuer = AysConfigurationParameter.AYS.getDefaultValue();
          log.info("Application configuration parameter has been set. tokenIssuer:{}", tokenIssuer);
  
          final String encryptedPrivateKey = Optional
                  .ofNullable(AysParameter.getDefinition(AysConfigurationParameter.AUTH_TOKEN_PRIVATE_KEY, configurationParameters))
                  .orElse(AysConfigurationParameter.AUTH_TOKEN_PRIVATE_KEY.getDefaultValue());
          this.tokenPrivateKey = AysKeyConverter.convertPrivateKey(encryptedPrivateKey);
          log.info("Application configuration parameter has been set. tokenPrivateKey:{}", encryptedPrivateKey.substring(0, 100).concat("..."));
  
          final String encryptedPublicKey = Optional
                  .ofNullable(AysParameter.getDefinition(AysConfigurationParameter.AUTH_TOKEN_PUBLIC_KEY, configurationParameters))
                  .orElse(AysConfigurationParameter.AUTH_TOKEN_PUBLIC_KEY.getDefaultValue());
          this.tokenPublicKey = AysKeyConverter.convertPublicKey(encryptedPublicKey);
          log.info("Application configuration parameter has been set. tokenPublicKey:{}", encryptedPublicKey.substring(0, 100).concat("..."));
  
          this.accessTokenExpireMinute = Optional
                  .ofNullable(AysParameter.getDefinition(AysConfigurationParameter.AUTH_ACCESS_TOKEN_EXPIRE_MINUTE, configurationParameters))
                  .map(Integer::valueOf)
                  .orElse(Integer.valueOf(AysConfigurationParameter.AUTH_ACCESS_TOKEN_EXPIRE_MINUTE.getDefaultValue()));
          log.info("Application configuration parameter has been set. accessTokenExpireMinute:{}", accessTokenExpireMinute);
  
          this.refreshTokenExpireMinute = Optional
                  .ofNullable(AysParameter.getDefinition(AysConfigurationParameter.AUTH_REFRESH_TOKEN_EXPIRE_MINUTE, configurationParameters))
                  .map(Integer::valueOf)
                  .orElse(Integer.valueOf(AysConfigurationParameter.AUTH_REFRESH_TOKEN_EXPIRE_MINUTE.getDefaultValue()));
          log.info("Application configuration parameter has been set. refreshTokenExpireMinute:{}", refreshTokenExpireMinute);
  
          this.feUrl = Optional
                  .ofNullable(AysParameter.getDefinition(AysConfigurationParameter.FE_URL, configurationParameters))
                  .orElse(AysConfigurationParameter.FE_URL.getDefaultValue());
          log.info("Application configuration parameter has been set. feUrl:{}", feUrl);
  
          log.info("Application Configuration Parameters read!");
      }
  
  }
  