package com.airlock.iam.plugin.config.manipulator.serializer;

import com.airlock.iam.plugin.api.config.PluginConfiguration;
import com.airlock.iam.plugin.framework.application.configuration.MutablePluginConfiguration;
import com.airlock.iam.plugin.framework.application.service.ConfigWriter;
import com.airlock.iam.plugin.framework.misc.PluginFramework;
import com.airlock.iam.plugin.framework.misc.config.ConfigHistoryItem;
import com.airlock.iam.plugin.framework.misc.frompersistence.TranslatedMedusaConfiguration;
import com.airlock.iam.system.config.ConfigFormat;
import com.airlock.iam.system.version.IamVersion;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public final class IamConfigurationSerializer {
   private final List<PluginConfiguration> configRoots = new ArrayList<>();
   private final List<ConfigHistoryItem> history = new ArrayList<>();

   public IamConfigurationSerializer addConfigRoot(PluginConfiguration configuration, String displayName) {
      this.configRoots.removeIf(pluginConfig -> Objects.requireNonNull(pluginConfig.getPluginDisplayName()).equals(displayName));
      this.configRoots.add(configuration);
      return this;
   }

   public IamConfigurationSerializer addHistoryItem(ConfigHistoryItem historyItem) {
      this.history.add(historyItem);
      return this;
   }

   private void writeConfigFile(ConfigFormat format, OutputStream os, IamVersion version) {
      try {
         TranslatedMedusaConfiguration translatedConfig = new TranslatedMedusaConfiguration(
            this.configRoots.stream().map(MutablePluginConfiguration.class::cast).toList(), false
         );
         translatedConfig.setIamVersion(version);
         this.history.forEach(translatedConfig::addHistoryItem);
         PluginFramework.getTranslatedConfigWriter(format).writeConfig(translatedConfig, os);
      } catch (ConfigWriter.ConfigWriterException e) {
         throw new IllegalStateException("Error writing configuration.", e);
      }
   }

   public String serializeToXmlString(IamVersion version) {
      ByteArrayOutputStream configStream = new ByteArrayOutputStream();
      this.writeConfigFile(ConfigFormat.XML_FORMAT, configStream, version);
      return configStream.toString(StandardCharsets.UTF_8);
   }

   public String serializeToYamlString(IamVersion version) {
      ByteArrayOutputStream configStream = new ByteArrayOutputStream();
      this.writeConfigFile(ConfigFormat.YAML_FORMAT, configStream, version);
      return configStream.toString(StandardCharsets.UTF_8);
   }

   public void writeToXmlFile(Path file, IamVersion version) throws IOException {
      try (OutputStream stream = Files.newOutputStream(file)) {
         this.writeConfigFile(ConfigFormat.XML_FORMAT, stream, version);
      }
   }

   public void writeToYamlFile(Path file, IamVersion version) throws IOException {
      try (OutputStream stream = Files.newOutputStream(file)) {
         this.writeConfigFile(ConfigFormat.YAML_FORMAT, stream, version);
      }
   }
}
