using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Spectre.Console.Cli;

namespace Shared.Rcl;

public static class ServiceCollectionExtensions {
    public static IServiceCollection AddCommands(
        this IServiceCollection services) {
        IEnumerable<Type>? commandTypes = Assembly.GetAssembly(typeof(ServiceCollectionExtensions))
            ?.GetTypes()
            .Where(t =>
                t is { IsAbstract: false, IsInterface: false } &&
                IsAsyncCommand(t)
            );

        if (commandTypes != null)
            foreach (Type type in commandTypes)
                services.AddScoped(type);

        return services;
    }

    private static bool IsAsyncCommand(Type type) {
        while (type != null) {
            if (type.IsGenericType &&
                type.GetGenericTypeDefinition() == typeof(AsyncCommand<>))
                return true;

            if (type == typeof(AsyncCommand))
                return true;

            type = type.BaseType!;
        }

        return false;
    }
}
