using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Kit.Helpers;
using Kit.Helpers.Cache;
using Kit.Helpers.Repository;
using Kit.Helpers.Service;

namespace RiskProf.Files.Dependency;

public static class Services
{
    public static IServiceCollection AddModuleMemoryCache(this IServiceCollection services)
    {
        services.AddSingleton<IMemoryCache, MemoryCache>();

        services.AddSingleton<ICacheProvider, MemoryCacheProvider>();

        return services;
    }

    public static IServiceCollection AddModuleHardwareId(this IServiceCollection services, bool needDebugProvider)
    {
        IHardwareInfoProvider infoProvider = null!;

        if (needDebugProvider)
        {
            infoProvider = new HardwareInfoProviderDebug();
        }
        else if (OperatingSystem.IsWindows())
        {
            infoProvider = new HardwareInfoProviderWindows();
        }
        else if (OperatingSystem.IsLinux())
        {
            infoProvider = new HardwareInfoProviderLinux();
        }

        if (infoProvider == null)
        {
            throw new ApplicationException($"{nameof(infoProvider)} is null");
        }

        services.AddSingleton(infoProvider);
        services.AddSingleton<IHardwareInfoService, HardwareInfoService>();

        return services;
    }

    public static IServiceCollection AddModuleSQLite(this IServiceCollection services)
    {
        services.AddSingleton<ISQLiteGlobalVarRepository, SQLiteGlobalVarRepository>();
        services.AddSingleton<ISQLiteVersionRepository, SQLiteVersionRepository>();
        services.AddSingleton<ISQLiteVersionService, SQLiteVersionService>();
        services.AddSingleton<ISQLiteFileFullPathFactory, SQLiteFileFullPathFactory>();
        services.AddSQLiteUpdateItems();

        return services;
    }

    public static void AddSQLiteUpdateItems(this IServiceCollection services)
    {
        var interfaceType = typeof(ISQLiteVersionUpdateItem);

        var assemblies = AppDomain.CurrentDomain.GetAssemblies();
        var implementationTypes = assemblies.SelectMany(x => x.GetTypes()).Where(t => interfaceType.IsAssignableFrom(t) && t.IsInterface == false && t.IsAbstract == false);

        implementationTypes.ForEach(implementationType => services.AddTransient(interfaceType, implementationType));
    }
}