package io.apicurio.registry.utils.reflectgen;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Set;
import java.util.stream.Collectors;

import org.reflections.Reflections;

import static org.reflections.scanners.Scanners.SubTypes;

/**
 * Generates the list of classes that need to be registered for reflection in native builds.
 * This class scans the apicurio-data-models library for all ValidationRule and Node subclasses
 * and generates Java source code for the ApicurioRegisterForReflection annotation.
 *
 * This is a build-time utility that runs during the generate-sources Maven phase.
 *
 * Usage: Run this class with one argument:
 * - Output file path where the generated class should be written
 */
public class ReflectionRegistryGenerator {

    public static void main(String[] args) throws IOException {
        if (args.length != 1) {
            System.err.println("Usage: ReflectionRegistryGenerator <output-file>");
            System.exit(1);
        }

        String outputPath = args[0];
        String generatedContent = generateClassList();

        writeToFile(outputPath, generatedContent);
        System.out.println("Successfully generated ApicurioRegisterForReflection at " + outputPath);
    }

    /**
     * Scans the classpath and generates the class list for reflection registration.
     *
     * @return The generated Java source code content
     */
    private static String generateClassList() {
        Reflections reflections = new Reflections("io.apicurio");

        Set<Class<?>> subTypes = reflections.get(SubTypes.of(io.apicurio.datamodels.validation.ValidationRule.class).asClass());
        subTypes.addAll(reflections.get(SubTypes.of(io.apicurio.datamodels.models.Node.class).asClass()));

        String classList = subTypes
            .stream()
            .map(t -> "        " + t.getCanonicalName() + ".class,")
            .sorted()
            .collect(Collectors.joining("\n"));

        return buildSourceFile(classList);
    }

    /**
     * Builds the complete Java source file content.
     *
     * @param classList The formatted list of classes
     * @return The complete Java source file as a string
     */
    private static String buildSourceFile(String classList) {
        return """
package io.apicurio.registry;

import io.apicurio.rest.client.auth.AccessTokenResponse;
import io.quarkus.runtime.annotations.RegisterForReflection;

/**
 * AUTOMATICALLY GENERATED - DO NOT EDIT
 *
 * This class is generated during the Maven build process by ReflectionRegistryGenerator.
 * It registers classes from apicurio-data-models for reflection in GraalVM native images.
 *
 * To regenerate: mvn clean compile
 */
@RegisterForReflection(targets = { AccessTokenResponse.class, io.agroal.pool.ConnectionHandler[].class,
        // The following list is automatically generated by scanning apicurio-data-models
""" + classList + """

})
public class ApicurioRegisterForReflection {

}
""";
    }

    /**
     * Writes the generated content to a file.
     *
     * @param outputPath Path to the output file
     * @param content Content to write
     */
    private static void writeToFile(String outputPath, String content) throws IOException {
        Path path = Paths.get(outputPath);
        Files.createDirectories(path.getParent());
        Files.writeString(path, content);
    }
}
