using Microsoft.Extensions.Options;

namespace Nexus.Api.Services;

public sealed class StaleTaskRecoveryBackgroundService(
    IServiceScopeFactory scopeFactory,
    IOptionsMonitor<StaleTaskRecoveryOptions> optionsMonitor,
    ILogger<StaleTaskRecoveryBackgroundService> logger) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                var resetCount = await RunRecoveryOnceAsync(stoppingToken);
                if (resetCount > 0)
                    logger.LogInformation("Stale task recovery reset {ResetCount} task(s).", resetCount);
            }
            catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
            {
                break;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Stale task recovery run failed.");
            }

            try
            {
                await Task.Delay(optionsMonitor.CurrentValue.GetInterval(), stoppingToken);
            }
            catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
            {
                break;
            }
        }
    }

    public async Task<int> RunRecoveryOnceAsync(CancellationToken ct = default)
    {
        await using var scope = scopeFactory.CreateAsyncScope();
        var recoveryService = scope.ServiceProvider.GetRequiredService<IStaleTaskRecoveryService>();
        return await recoveryService.ResetStaleInProgressTasksAsync(optionsMonitor.CurrentValue.GetStaleThreshold(), ct);
    }
}
