using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Services.Notifications;
using AsbCloudInfrastructure.Background;
using Microsoft.Extensions.DependencyInjection;

namespace AsbCloudWebApi.SignalR.Services;

public class SignalRNotificationTransportService : INotificationTransportService
{
   private readonly NotificationBackgroundWorker backgroundWorker;

   public SignalRNotificationTransportService(NotificationBackgroundWorker backgroundWorker)
   {
      this.backgroundWorker = backgroundWorker;
   }

   public int IdTransportType => 0;

   public Task SendAsync(NotificationDto notification,
      CancellationToken cancellationToken) => SendRangeAsync(new[] { notification }, cancellationToken);

   public Task SendRangeAsync(IEnumerable<NotificationDto> notifications, 
      CancellationToken cancellationToken)
   {
      var workId = HashCode.Combine(notifications.Select(n => n.Id)).ToString("x");

      if (backgroundWorker.Works.Any(w => w.Id == workId)) 
         return Task.CompletedTask;

      var workAction = MakeSignalRSendWorkAction(notifications);
      var work = Work.CreateByDelegate(workId, workAction);
      backgroundWorker.Enqueue(work);

      return Task.CompletedTask;
   }

   private Func<string, IServiceProvider, Action<string, double?>, CancellationToken, Task> MakeSignalRSendWorkAction(IEnumerable<NotificationDto> notifications)
   {
      return async (_, serviceProvider, onProgress, cancellationToken) =>
      {
         var notificationPublisher = serviceProvider.GetRequiredService<NotificationPublisher>();

         var groupedNotificationsByUsers = notifications.GroupBy(n => n.IdUser);
         
         foreach (var groupedNotificationByUser in groupedNotificationsByUsers)
         {
            await notificationPublisher.PublishAsync(groupedNotificationByUser, cancellationToken);   
         }
      };
   }
}