using System.Reflection;
using Femto.Common.Attributes;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Quartz;

namespace Femto.Common.Infrastructure.Outbox;

public static class OutboxServiceExtension
{
    public static void AddOutbox<TContext, TMessageHandler>(
        this IServiceCollection services,
        Func<IServiceProvider, TContext>? contextFactory = null
    )
        where TContext : DbContext, IOutboxContext
        where TMessageHandler : class, IOutboxMessageHandler
    {
        services.AddSingleton<IOutboxMessageMapping, ClrTypenameMessageMapping>();

        services.AddScoped<IOutboxContext>(c =>
            contextFactory?.Invoke(c) ?? c.GetRequiredService<TContext>()
        );

        services.AddScoped<Outbox<TContext>>();

        services.AddScoped<IOutboxMessageHandler, TMessageHandler>();

        services.AddQuartz(q =>
        {
            var jobKey = JobKey.Create(nameof(OutboxProcessor<TContext>));

            q.AddJob<OutboxProcessor<TContext>>(jobKey)
                .AddTrigger(trigger =>
                    trigger
                        .ForJob(jobKey)
                        .WithSimpleSchedule(schedule =>
                            schedule.WithIntervalInSeconds(1).RepeatForever()
                        )
                );
        });
    }
}
