File size: 4,286 Bytes
4433399
ccc2569
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4433399
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
using LibraryManagement.Shared.Models;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DbConnect.Data;
using Microsoft.EntityFrameworkCore;

namespace Backend.Features.Notification;

public class NotificationBackgroundService : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;
    private readonly TimeSpan _checkInterval = TimeSpan.FromHours(24); // Check once a day

    public NotificationBackgroundService(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                using (var scope = _serviceProvider.CreateScope())
                {
                    var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
                    var notificationService = scope.ServiceProvider.GetRequiredService<INotificationService>();

                    await CheckSubscriptionExpiries(context, notificationService);
                    await CheckBorrowingReminders(context, notificationService);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error in NotificationBackgroundService: {ex.Message}");
            }

            await Task.Delay(_checkInterval, stoppingToken);
        }
    }

    private async Task CheckSubscriptionExpiries(AppDbContext context, INotificationService notificationService)
    {
        var targetDate = DateTime.Today.AddDays(25);
        
        var expiringSubscriptions = await context.UserSubscriptions
            .Include(s => s.User)
            .Where(s => s.IsActive && s.ExpiryDate.Date <= targetDate)
            .ToListAsync();

        foreach (var sub in expiringSubscriptions)
        {
            // Check if notification already sent TODAY to avoid duplicates on restart
            var alreadySentToday = await context.Notifications.AnyAsync(n => 
                n.UserId == sub.UserId && 
                n.Title == "Subscription Renewal Reminder" && 
                n.CreatedAt >= DateTime.Today);

            if (alreadySentToday) continue;

            string title = "Subscription Renewal Reminder";
            string message = $"Hello {sub.User.FullName}, your library subscription will expire soon ({sub.ExpiryDate:MMM dd, yyyy}). Renew now to avoid interruption!";
            
            await notificationService.SendAndSaveNotificationAsync(
                sub.UserId, 
                sub.User.FcmToken, 
                title, 
                message, 
                "Warning", 
                "/Membership", 
                "Renew Now");
        }
    }

    private async Task CheckBorrowingReminders(AppDbContext context, INotificationService notificationService)
    {
        var targetDate = DateTime.Today.AddDays(10);

        var dueBorrowings = await context.Borrowings
            .Include(b => b.User)
            .Include(b => b.Book)
            .Where(b => b.Status == "Borrowed" && b.DueDate.Date <= targetDate)
            .ToListAsync();

        foreach (var loan in dueBorrowings)
        {
            // Check if notification already sent for this specific book TODAY
            var alreadySentToday = await context.Notifications.AnyAsync(n => 
                n.UserId == loan.UserId && 
                n.Title == "Book Return Reminder" && 
                n.Message.Contains(loan.Book.Title) &&
                n.CreatedAt >= DateTime.Today);

            if (alreadySentToday) continue;

            string title = "Book Return Reminder";
            string message = $"Hello {loan.User.FullName}, the book '{loan.Book.Title}' is due soon ({loan.DueDate:MMM dd, yyyy}). Please remember to return it on time!";
            
            await notificationService.SendAndSaveNotificationAsync(
                loan.UserId, 
                loan.User.FcmToken, 
                title, 
                message, 
                "Info", 
                "/Borrowings", 
                "View My Loans");
        }
    }
}