using DigitalData.Core.Abstractions.Security.Services;
using DigitalData.Core.Security.Config;
using DigitalData.Core.Security.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Security.Claims;

namespace DigitalData.Core.Security.Extensions;

public static class DIExtensions
{
    /// <summary>
    /// Registers a custom asym crypt service with specified parameters from the given configuration section.
    /// </summary>
    /// <param name="services"></param>
    /// <param name="configuration"></param>
    /// <returns>The updated <see cref="IServiceCollection"/> with the RSA Factory registered.</returns>
    public static IServiceCollection AddRSAPool(this IServiceCollection services, IConfiguration configuration) => services
        .Configure<RSAParams>(configuration)
        .AddAutoMapper(typeof(MappingProfile).Assembly)
        .AddSingleton<IAsymmetricKeyPool, RSAPool>()
        .AddSingleton<IAsymmetricKeyFactory, RSAFactory>()
        .AddHostedService<PemFileInitalizer>();

    /// <summary>
    /// Registers a custom asym crypt service with specified parameters from the given configuration section.
    /// </summary>
    /// <param name="services"></param>
    /// <param name="rsaParams"></param>
    /// <returns>The updated <see cref="IServiceCollection"/> with the RSA Factory registered.</returns>
    public static IServiceCollection AddRSAPool(this IServiceCollection services, RSAParams rsaParams) => services
        .AddSingleton(Options.Create(rsaParams))
        .AddAutoMapper(typeof(MappingProfile).Assembly)
        .AddSingleton<IAsymmetricKeyPool, RSAPool>()
        .AddSingleton<IAsymmetricKeyFactory, RSAFactory>()
        .AddHostedService<PemFileInitalizer>();

    public static IServiceCollection AddJwtSignatureHandler<TPrincipal>(this IServiceCollection services,
        Func<TPrincipal, IDictionary<string, object>>? claimsMapper = null,
        Func<TPrincipal, ClaimsIdentity>? subjectMapper = null)
        => services
            .AddSingleton<IJwtSignatureHandler<TPrincipal>, JwtSignatureHandler<TPrincipal>>()
            .AddSingleton(sp => Options.Create(new ClaimDescriptor<TPrincipal>
            {
                CreateClaims = claimsMapper,
                CreateSubject = subjectMapper
            }));
}