using Microsoft.EntityFrameworkCore;
using Nexus.Api.Data;
using Nexus.Api.Models;

namespace Nexus.Api.Services;

public sealed class NotificationService(NexusDbContext db) : INotificationService
{
    public async Task<Notification> CreateAsync(string type, string title, string? message, string forUser, Guid? taskId = null, CancellationToken ct = default)
    {
        var notification = new Notification
        {
            Type = type,
            Title = title,
            Message = message,
            ForUser = forUser.ToLowerInvariant(),
            TaskId = taskId
        };
        db.Notifications.Add(notification);
        await db.SaveChangesAsync(ct);
        return notification;
    }

    public async Task<IReadOnlyList<Notification>> GetForUserAsync(string forUser, int limit = 50, bool unreadOnly = false, CancellationToken ct = default)
    {
        var query = db.Notifications
            .Where(n => n.ForUser == forUser.ToLowerInvariant());

        if (unreadOnly)
            query = query.Where(n => !n.IsRead);

        return await query
            .OrderByDescending(n => n.CreatedAt)
            .Take(limit)
            .ToListAsync(ct);
    }

    public async Task<bool> MarkAsReadAsync(Guid id, CancellationToken ct = default)
    {
        var notification = await db.Notifications.FindAsync([id], ct);
        if (notification is null) return false;

        notification.IsRead = true;
        await db.SaveChangesAsync(ct);
        return true;
    }

    public async Task<int> MarkAllAsReadAsync(string forUser, CancellationToken ct = default)
    {
        var count = await db.Notifications
            .Where(n => n.ForUser == forUser.ToLowerInvariant() && !n.IsRead)
            .ExecuteUpdateAsync(s => s.SetProperty(n => n.IsRead, true), ct);
        return count;
    }

    public async Task<int> GetUnreadCountAsync(string forUser, CancellationToken ct = default)
    {
        return await db.Notifications
            .CountAsync(n => n.ForUser == forUser.ToLowerInvariant() && !n.IsRead, ct);
    }
}
