using MassTransit;

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

using Monitoring.Common;
using Monitoring.Core.Domain.RolePrimitives;
using Monitoring.Core.Domain.UserPrimitives;
using Monitoring.Infrastructure.Data;
using Monitoring.Notifications.Events;

namespace Monitoring.Services;

internal sealed class NotificationService(
	DataContext dataContext,
	ILogger<NotificationService> logger,
	IRequestClient<NotificationSent> bus
) : INotificationService
{
	private const string Method = "NOTIFICATION";

	public async Task NotifyAdministrators<T>(
		T model,
		string method,
		CancellationToken cancellationToken)
	{
		var administratorRoleUpperCaseName = RoleUpperCaseName.Create(Roles.Administrator);

		var receiverList = await dataContext.Users
			.Where(x => x.Role.UpperCaseName == administratorRoleUpperCaseName)
			.Select(x => x.Id)
			.ToListAsync(cancellationToken);

		logger.LogInformation(
			"Try to notify administrators: {Count}\r\n{List}",
			receiverList.Count,
			string.Join(", ", receiverList));

		await NotifyUsers(receiverList, method, model, cancellationToken);
	}

	public Task NotifyUsers<T>(
		IEnumerable<UserId> userIdList,
		string method,
		T model,
		CancellationToken cancellationToken)
	{
		return bus.GetResponse<NotificationSentResponse>(new NotificationSent(
			userIdList.Select(x => x.Value),
			Method,
			new NotificationModel<T>(method, model)),
			cancellationToken);
	}
}