using Health.Application.Notifications;

namespace Health.WebApi.BackgroundServices;

/// <summary>
/// Produces in-app catch-up reminders for health records.
/// The actual reminder rules live in IReminderCatchUpService so foreground
/// app checks and background scans stay consistent.
/// </summary>
public sealed class HealthRecordReminderService(
    IServiceScopeFactory scopeFactory,
    ILogger<HealthRecordReminderService> logger) : BackgroundService
{
    private static readonly int[] ReminderHoursCst = [9, 13, 19];
    private DateTime _lastFired = DateTime.MinValue;

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation("Health record in-app reminder service started");
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                var nowCst = DateTime.UtcNow.AddHours(8);
                if (ReminderHoursCst.Contains(nowCst.Hour) &&
                    (_lastFired.Date != nowCst.Date || _lastFired.Hour != nowCst.Hour))
                {
                    await CheckUsersAsync(DateTime.UtcNow, stoppingToken);
                    _lastFired = nowCst;
                }
            }
            catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
            {
                break;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Health record in-app reminder scan failed");
            }

            await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
        }
    }

    private async Task CheckUsersAsync(DateTime utcNow, CancellationToken ct)
    {
        using var scope = scopeFactory.CreateScope();
        var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
        var catchUp = scope.ServiceProvider.GetRequiredService<IReminderCatchUpService>();

        var userIds = await db.NotificationPreferences.AsNoTracking()
            .Where(x => x.PushEnabled && x.HealthRecordReminder)
            .Select(x => x.UserId)
            .ToListAsync(ct);

        var created = 0;
        foreach (var userId in userIds)
        {
            var result = await catchUp.CheckDueAsync(userId, utcNow, ct);
            created += result.CreatedCount;
        }

        if (created > 0)
            logger.LogInformation("Created {Count} in-app catch-up reminders", created);
    }
}
