package click.kamil.springstatemachineexporter.analysis.util;

import lombok.extern.slf4j.Slf4j;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Utility for resolving Spring-style placeholders like ${property.name} or ${property.name:default-value}.
 * Supports recursive resolution.
 */
@Slf4j
public class PlaceholderResolver {

    private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\$\\{([^:}]+)(?::([^}]*))?}");

    /**
     * Resolves all placeholders in the given text using the provided properties map.
     *
     * @param text       The text containing placeholders.
     * @param properties The map of property keys and values.
     * @return The resolved string.
     */
    public static String resolve(String text, Map<String, String> properties) {
        return resolveInternal(text, properties, new HashSet<>());
    }

    private static String resolveInternal(String text, Map<String, String> properties, Set<String> visited) {
        if (text == null || !text.contains("${")) {
            return text;
        }

        StringBuilder result = new StringBuilder();
        Matcher matcher = PLACEHOLDER_PATTERN.matcher(text);
        int lastMatchEnd = 0;

        while (matcher.find()) {
            result.append(text, lastMatchEnd, matcher.start());
            String key = matcher.group(1);
            String defaultValue = matcher.group(2);

            if (visited.contains(key)) {
                log.warn("Circular placeholder reference detected: {}", key);
                result.append(matcher.group(0)); // Keep as is
            } else {
                String value = properties.get(key);
                if (value == null) {
                    value = defaultValue;
                }

                if (value != null) {
                    visited.add(key);
                    try {
                        result.append(resolveInternal(value, properties, visited));
                    } finally {
                        visited.remove(key);
                    }
                } else {
                    log.debug("Property not found and no default value for: {}", key);
                    result.append(matcher.group(0)); // Keep as is if not resolvable
                }
            }
            lastMatchEnd = matcher.end();
        }
        result.append(text.substring(lastMatchEnd));

        return result.toString();
    }
}
