using Ikar.Server.Infrastructure.Hubs;
using Ikar.Shared;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Options;

namespace Ikar.Server.Infrastructure.Calls;

public sealed class CallSessionCleanupService(
    CallSessionStore store,
    IHubContext<MessengerHub> hubContext,
    IOptions<WebRtcOptions> options,
    ILogger<CallSessionCleanupService> logger) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        using var timer = new PeriodicTimer(TimeSpan.FromSeconds(5));
        while (await timer.WaitForNextTickAsync(stoppingToken))
        {
            var expired = store.DrainExpired(
                DateTimeOffset.UtcNow,
                TimeSpan.FromSeconds(Math.Clamp(options.Value.RingingTimeoutSeconds, 15, 300)),
                TimeSpan.FromHours(Math.Clamp(options.Value.MaximumCallDurationHours, 1, 24)));
            foreach (var session in expired)
            {
                var payload = new CallEndedDto(
                    session.CallId,
                    session.ChatId,
                    session.EndReason,
                    session.MediaType);
                await Task.WhenAll(
                    hubContext.Clients.User(session.CallerId.ToString()).SendAsync("CallEnded", payload, stoppingToken),
                    hubContext.Clients.User(session.CalleeId.ToString()).SendAsync("CallEnded", payload, stoppingToken));
                logger.LogInformation(
                    "Expired call session {CallId} with reason {Reason}.",
                    session.CallId,
                    session.EndReason);
            }
        }
    }
}
