using Health.Application.Notifications;

namespace Health.Infrastructure.Notifications;

public sealed class EfInAppNotificationRepository(AppDbContext db) : IInAppNotificationRepository
{
    private readonly AppDbContext _db = db;

    public async Task<IReadOnlyList<InAppNotificationRecord>> GetPendingAsync(Guid userId, CancellationToken ct) =>
        await _db.UserNotifications.AsNoTracking()
            .Where(x => x.UserId == userId && !x.IsRead && !x.IsDeleted)
            .OrderBy(x => x.CreatedAt)
            .Take(10)
            .Select(x => new InAppNotificationRecord(x.Id, x.Type, x.Title, x.Message,
                x.Severity, x.ActionType, x.ActionTargetId, x.IsRead, x.CreatedAt))
            .ToListAsync(ct);

    public async Task<IReadOnlyList<InAppNotificationRecord>> GetHistoryAsync(Guid userId, CancellationToken ct) =>
        await _db.UserNotifications.AsNoTracking()
            .Where(x => x.UserId == userId && !x.IsDeleted)
            .OrderByDescending(x => x.CreatedAt)
            .Take(100)
            .Select(x => new InAppNotificationRecord(x.Id, x.Type, x.Title, x.Message,
                x.Severity, x.ActionType, x.ActionTargetId, x.IsRead, x.CreatedAt))
            .ToListAsync(ct);

    public async Task<bool> AcknowledgeAsync(Guid userId, Guid notificationId, CancellationToken ct)
    {
        var updated = await _db.UserNotifications
            .Where(x => x.Id == notificationId && x.UserId == userId && !x.IsRead && !x.IsDeleted)
            .ExecuteUpdateAsync(setters => setters
                .SetProperty(x => x.IsRead, true)
                .SetProperty(x => x.ReadAt, DateTime.UtcNow), ct);
        return updated > 0;
    }

    public Task<int> MarkAllReadAsync(Guid userId, CancellationToken ct) =>
        _db.UserNotifications
            .Where(x => x.UserId == userId && !x.IsRead && !x.IsDeleted)
            .ExecuteUpdateAsync(setters => setters
                .SetProperty(x => x.IsRead, true)
                .SetProperty(x => x.ReadAt, DateTime.UtcNow), ct);

    public async Task<bool> DeleteAsync(Guid userId, Guid notificationId, CancellationToken ct)
    {
        var deleted = await _db.UserNotifications
            .Where(x => x.Id == notificationId && x.UserId == userId && !x.IsDeleted)
            .ExecuteUpdateAsync(setters => setters
                .SetProperty(x => x.IsDeleted, true), ct);
        return deleted > 0;
    }
}
