using JobsMedical.Web.Services.Scraping;

namespace JobsMedical.Web.Services.Social;

/// <summary>
/// Posts the daily «آماده به کار» digest to Telegram/Bale on a schedule — SocialPostsPerDay times
/// a day, evenly spaced. Reads settings fresh each cycle so it can be toggled from the admin panel
/// without a redeploy. Idle and self-paced; the manual «ارسال اکنون» button uses the same service.
/// </summary>
public class SocialPostWorker : BackgroundService
{
    private readonly IServiceScopeFactory _scopes;
    private readonly ILogger<SocialPostWorker> _log;

    public SocialPostWorker(IServiceScopeFactory scopes, ILogger<SocialPostWorker> log)
    {
        _scopes = scopes; _log = log;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        try { await Task.Delay(TimeSpan.FromSeconds(40), stoppingToken); }
        catch (OperationCanceledException) { return; }

        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                using var scope = _scopes.CreateScope();
                var settings = await scope.ServiceProvider.GetRequiredService<SettingsService>().GetAsync();

                if (settings.SocialEnabled)
                {
                    var perDay = Math.Clamp(settings.SocialPostsPerDay, 1, 24);
                    var interval = TimeSpan.FromHours(24.0 / perDay);
                    var due = settings.SocialLastPostedAt is null
                              || DateTime.UtcNow - settings.SocialLastPostedAt.Value >= interval;
                    if (due)
                    {
                        var result = await scope.ServiceProvider.GetRequiredService<SocialPostService>().PostAsync(stoppingToken);
                        _log.LogInformation("Social digest posted: tg={Tg} bale={Bale} count={Count} err={Err}",
                            result.TelegramOk, result.BaleOk, result.Count, result.Error);
                    }
                }
            }
            catch (Exception ex) when (ex is not OperationCanceledException)
            {
                _log.LogError(ex, "Social post cycle failed");
            }

            // Check fairly often (15 min) so toggles/interval changes take effect; PostAsync itself
            // is gated by SocialLastPostedAt so we never over-post.
            try { await Task.Delay(TimeSpan.FromMinutes(15), stoppingToken); }
            catch (OperationCanceledException) { break; }
        }
    }
}
