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

import com.airlock.iam.plugin.framework.misc.util.PluginConfigurationDictionaryUtils;
import com.airlock.iam.system.config.ConfigFormat;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.nio.file.Path;
import java.util.Optional;
import java.util.function.Consumer;

@SuppressFBWarnings("DM_EXIT")
public final class ConfigSnippetImporterMain {
   private ConfigSnippetImporterMain() {
   }

   public static void main(String... args) {
      if (args.length != 5) {
         System.err.println("expected arguments: configFile, configSnippet, onDisplayNameConflict, [idSuffix], [outputFile]");
         System.exit(1);
      } else {
         Path configFile = Path.of(args[0]);
         Path configSnippet = Path.of(args[1]);
         OnDisplayNameConflict onDisplayNameConflict = OnDisplayNameConflict.fromCliValue(args[2]);
         Optional<String> idSuffix = args[3].isBlank() ? Optional.empty() : Optional.of(args[3]);
         Optional<Path> outputFile = args[4].isBlank() ? Optional.empty() : Optional.of(Path.of(args[4]));

         try {
            ConfigManipulationService service = new ConfigManipulationService(configFile);
            SnippetImportResult result = service.importConfigurationSnippet(configSnippet, onDisplayNameConflict, idSuffix);
            if (result.hasFailures()) {
               printFailureResult(result);
               System.exit(1);
               return;
            }

            PluginConfigurationDictionaryUtils.atomicWriteDictionaryToFile(result.dictionary(), ConfigFormat.YAML_FORMAT, outputFile.orElse(configFile));
            printSuccessResult(result);
         } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
            System.exit(1);
         }
      }
   }

   private static void printFailureResult(SnippetImportResult result) {
      System.err
         .printf(
            "Snippet import aborted due to failures while applying modifications. All changes have been rolled back. Summary: VALID=%d SKIPPED=%s FAILED=%d%n",
            result.getValidModificationsCount(),
            result.getSkippedModificationCount(),
            result.getFailureModificationCount()
         );
      printSnippetImportModificationResults(result, System.err::println);
   }

   private static void printSnippetImportModificationResults(SnippetImportResult result, Consumer<String> outputStream) {
      result.modificationResults().forEach(modificationResult -> outputStream.accept(formatModificationResult(modificationResult)));
   }

   private static String formatModificationResult(ModificationResult modificationResult) {
      return "%s: %s - %s".formatted(modificationResult.status().name(), modificationResult.identifier(), modificationResult.message());
   }

   private static void printSuccessResult(SnippetImportResult result) {
      if (!result.hasModificationResults()) {
         System.out.println("Snippet import completed successfully.");
      } else {
         System.out
            .printf(
               "Snippet import completed successfully including modifications. Summary: VALID=%d SKIPPED=%s%n",
               result.getValidModificationsCount(),
               result.getSkippedModificationCount()
            );
         printSnippetImportModificationResults(result, System.out::println);
      }
   }
}
