package click.kamil.springstatemachineexporter.analysis.pipeline;

import java.util.Locale;
import java.util.Set;

/**
 * Central registry for reactive/factory unwrap and passthrough method names used during constant extraction.
 */
public final class LibraryUnwrapRegistry {

    private static final Set<String> UNWRAP_RECEIVER_TYPES = Set.of(
            "Optional", "Stream", "List", "Set", "Arrays", "Objects", "Mono", "Flux", "MessageBuilder");

    private static final Set<String> UNWRAP_METHOD_NAMES = Set.of(
            "of", "ofEntries", "asList", "entry", "just", "withPayload", "success");

    private static final Set<String> REACTIVE_FACTORY_METHODS = Set.of("just", "withPayload", "success");

    private static final Set<String> REACTIVE_TRANSFORM_METHODS = Set.of("map", "flatMap", "switchMap", "concatMap");

    /** Fixed header keys that may carry a machine event (free-form / dynamic keys stay fail-closed). */
    private static final Set<String> EVENT_HEADER_KEYS = Set.of("event", "smEvent");

    private static final String[] STOP_UNWRAP_PREFIXES = {
            "map", "parse", "convert", "to", "resolve", "build", "create", "from",
            "transform", "translate", "derive", "determine", "calculate", "decode",
            "extract", "get", "find", "validate"
    };

    private LibraryUnwrapRegistry() {
    }

    public static boolean isUnwrapReceiverType(String receiverExpressionText) {
        return receiverExpressionText != null && UNWRAP_RECEIVER_TYPES.contains(receiverExpressionText);
    }

    public static boolean isUnwrapMethodName(String methodName) {
        return methodName != null && UNWRAP_METHOD_NAMES.contains(methodName);
    }

    public static boolean isReactiveFactoryMethod(String methodName) {
        return methodName != null && REACTIVE_FACTORY_METHODS.contains(methodName);
    }

    public static boolean isReactiveTransformMethod(String methodName) {
        return methodName != null && REACTIVE_TRANSFORM_METHODS.contains(methodName);
    }

    public static boolean shouldStopUnwrap(String methodName) {
        if (methodName == null) {
            return true;
        }
        String lowerName = methodName.toLowerCase(Locale.ROOT);
        for (String prefix : STOP_UNWRAP_PREFIXES) {
            if (lowerName.startsWith(prefix)) {
                return true;
            }
        }
        return false;
    }

    public static boolean isEventSetterMethodName(String methodName) {
        if (methodName == null) {
            return false;
        }
        return "event".equalsIgnoreCase(methodName)
                || "type".equalsIgnoreCase(methodName)
                || "eventType".equalsIgnoreCase(methodName);
    }

    public static boolean isHeaderSetterMethodName(String methodName) {
        return "setHeader".equals(methodName);
    }

    public static boolean isEventHeaderKey(String headerKey) {
        return headerKey != null && EVENT_HEADER_KEYS.contains(headerKey);
    }

    public static boolean isGenericMessageType(String typeName) {
        if (typeName == null || typeName.isBlank()) {
            return false;
        }
        String simple = typeName.contains(".") ? typeName.substring(typeName.lastIndexOf('.') + 1) : typeName;
        int generic = simple.indexOf('<');
        if (generic >= 0) {
            simple = simple.substring(0, generic);
        }
        return "GenericMessage".equals(simple);
    }
}
