package com.airlock.iam.application.parameters.infrastructure;

import com.airlock.iam.elog.api.EDefaultLogType;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import jakarta.annotation.Nullable;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import java.util.Properties;
import java.util.function.Function;

public class ConfigRootResolver {
   public static final String IAM_CONFIG_ROOT_ENV = "IAM_CONFIG_ROOT";
   private static final ELogger LOG = ELoggerFactory.getLogger(ConfigRootResolver.class);
   private final Function<String, String> environment;
   private final Properties systemProperties;

   public ConfigRootResolver() {
      this.environment = System::getenv;
      this.systemProperties = System.getProperties();
   }

   ConfigRootResolver(Function<String, String> environment, Properties systemProperties) {
      this.environment = environment;
      this.systemProperties = systemProperties;
   }

   public Path resolveConfigRootWithFallback(@Nullable Path configRootFromOption) {
      return this.getExplicitConfigRoot(configRootFromOption).orElseGet(this::defaultConfigRoot);
   }

   public Optional<Path> resolveConfigRoot(@Nullable Path configRootFromOption) {
      return this.getExplicitConfigRoot(configRootFromOption);
   }

   Optional<Path> getExplicitConfigRoot(@Nullable Path configRootFromOption) {
      return configRootFromOption != null
         ? Optional.of(configRootFromOption)
         : this.findConfigRootFromEnv()
            .filter(
               path -> {
                  if (!path.isAbsolute()) {
                     LOG.error(
                        EDefaultLogType.GENERIC_LOG_TYPE,
                        String.format("The value of the environment property \"%s\" must be an absolute path, but was: %s", "IAM_CONFIG_ROOT", path)
                     );
                  }

                  return path.isAbsolute();
               }
            );
   }

   private Path defaultConfigRoot() {
      return Paths.get(this.systemProperties.getProperty("user.home"), "iam");
   }

   public Optional<Path> findConfigRootFromEnv() {
      String configRoot = this.environment.apply("IAM_CONFIG_ROOT");
      return Optional.ofNullable(configRoot).map(x$0 -> Paths.get(x$0)).map(Path::normalize);
   }
}
