using Microsoft.EntityFrameworkCore;
using Ikar.Server.Data;
using Ikar.Server.Data.Entities;

namespace Ikar.Server.Infrastructure.Push;

public sealed class PushNotificationDispatcher(
    IkarDbContext dbContext,
    IPushNotificationSender pushNotificationSender,
    ILogger<PushNotificationDispatcher> logger)
{
    public async Task DispatchMessageAsync(Chat chat, Message message, CancellationToken cancellationToken = default)
    {
        var recipientIds = chat.Members
            .Select(x => x.UserId)
            .Where(x => x != message.SenderId)
            .Distinct()
            .ToList();

        if (recipientIds.Count == 0)
        {
            return;
        }

        var devices = await dbContext.PushDevices
            .Where(x => recipientIds.Contains(x.UserId) && x.NotificationsEnabled)
            .ToListAsync(cancellationToken);

        if (devices.Count == 0)
        {
            return;
        }

        try
        {
            await pushNotificationSender.SendMessageAsync(chat, message, devices, cancellationToken);
        }
        catch (Exception ex)
        {
            logger.LogWarning(ex, "Push dispatch failed for message {MessageId}.", message.Id);
        }
    }

    public async Task DispatchMessageReactionAsync(
        Chat chat,
        Message message,
        User reactor,
        string emoji,
        CancellationToken cancellationToken = default)
    {
        if (message.SenderId == reactor.Id || string.IsNullOrWhiteSpace(emoji))
        {
            return;
        }

        var devices = await dbContext.PushDevices
            .Where(x => x.UserId == message.SenderId && x.NotificationsEnabled)
            .ToListAsync(cancellationToken);

        if (devices.Count == 0)
        {
            return;
        }

        try
        {
            await pushNotificationSender.SendMessageReactionAsync(
                chat,
                message,
                reactor,
                emoji,
                devices,
                cancellationToken);
        }
        catch (Exception ex)
        {
            logger.LogWarning(
                ex,
                "Push dispatch failed for reaction to message {MessageId}.",
                message.Id);
        }
    }
}
