package stirling.software.SPDF.config;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;

public class ConfigInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        try {
            ensureConfigExists();
        } catch (IOException e) {
            throw new RuntimeException("Failed to initialize application configuration", e);
        }
    }

    public void ensureConfigExists() throws IOException {
        // Define the path to the external config directory
        Path destPath = Paths.get("configs", "settings.yml");

        // Check if the file already exists
        if (Files.notExists(destPath)) {
            // Ensure the destination directory exists
            Files.createDirectories(destPath.getParent());

            // Copy the resource from classpath to the external directory
            try (InputStream in = getClass().getClassLoader().getResourceAsStream("settings.yml.template")) {
                if (in != null) {
                    Files.copy(in, destPath);
                } else {
                    throw new FileNotFoundException("Resource file not found: settings.yml.template");
                }
            }
        } else {
            // If user file exists, we need to merge it with the template from the classpath
            List<String> templateLines;
            try (InputStream in = getClass().getClassLoader().getResourceAsStream("settings.yml.template")) {
                templateLines = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)).lines().collect(Collectors.toList());
            }

            mergeYamlFiles(templateLines, destPath, destPath);
        }
    }

    public void mergeYamlFiles(List<String> templateLines, Path userFilePath, Path outputPath) throws IOException {
        List<String> userLines = Files.readAllLines(userFilePath);

        List<String> mergedLines = new ArrayList<>();
        boolean insideAutoGenerated = false;

        for (String line : templateLines) {
            // Check if we've entered or left the AutomaticallyGenerated section
            if (line.trim().equalsIgnoreCase("AutomaticallyGenerated:")) {
                insideAutoGenerated = true;
                mergedLines.add(line);
                continue;
            } else if (insideAutoGenerated && line.trim().isEmpty()) {
                // We have reached the end of the AutomaticallyGenerated section
                insideAutoGenerated = false;
                mergedLines.add(line);
                continue;
            }

            if (insideAutoGenerated) {
                // Add lines from user's settings if we are inside AutomaticallyGenerated
                Optional<String> userAutoGenValue = userLines.stream().filter(l -> l.trim().startsWith(line.split(":")[0].trim())).findFirst();
                if (userAutoGenValue.isPresent()) {
                    mergedLines.add(userAutoGenValue.get());
                    continue;
                }
            } else {
                // Outside of AutomaticallyGenerated, continue as before
                if (line.contains(": ")) {
                    String key = line.split(": ")[0].trim();
                    Optional<String> userValue = userLines.stream().filter(l -> l.trim().startsWith(key)).findFirst();
                    if (userValue.isPresent()) {
                        mergedLines.add(userValue.get());
                        continue;
                    }
                }
                mergedLines.add(line);
            }
        }

        Files.write(outputPath, mergedLines, StandardCharsets.UTF_8);
    }
}