using Application.Abstractions.Cache;
using Application.Abstractions.YouTube;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;

namespace Infrastructure.YouTube;

/// <summary>
/// PubSubHubbub 구독 자동 갱신 BackgroundService
/// 구독은 약 10일 후 만료 → 7일마다 재구독
/// </summary>
internal sealed class YouTubePubSubRenewalService(
    IYouTubePubSubService pubSubService,
    IConnectionMultiplexer redis,
    ILogger<YouTubePubSubRenewalService> logger
) : BackgroundService
{
    private static readonly TimeSpan RenewalInterval = TimeSpan.FromDays(7);
    private static readonly TimeSpan InitialDelay = TimeSpan.FromSeconds(30);

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await Task.Delay(InitialDelay, stoppingToken);

        logger.LogInformation("[PubSub Renewal] 서비스 시작 — 갱신 주기: {Interval}일", RenewalInterval.TotalDays);

        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                await RenewAllSubscriptionsAsync(stoppingToken);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "[PubSub Renewal] 구독 갱신 중 오류");
            }

            await Task.Delay(RenewalInterval, stoppingToken);
        }
    }

    private async Task RenewAllSubscriptionsAsync(CancellationToken ct)
    {
        var db = redis.GetDatabase();
        var channelIds = await db.SetMembersAsync(CacheKeys.YouTubePubSubChannels);

        if (channelIds.Length == 0)
        {
            logger.LogInformation("[PubSub Renewal] 구독 중인 채널 없음");
            return;
        }

        var renewed = 0;
        foreach (var channelId in channelIds)
        {
            var id = channelId.ToString();
            var success = await pubSubService.SubscribeAsync(id, ct);
            if (success)
            {
                renewed++;
            }

            // 요청 간 1초 간격
            await Task.Delay(TimeSpan.FromSeconds(1), ct);
        }

        logger.LogInformation("[PubSub Renewal] {Renewed}/{Total} 채널 구독 갱신 완료", renewed, channelIds.Length);
    }
}