using Govor.Domain; using Govor.Domain.Common; using Govor.Domain.Models.Users; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace Govor.Application.PushNotifications; public class PushTokenService : IPushTokenService { private readonly GovorDbContext _context; private readonly ILogger _logger; public PushTokenService(GovorDbContext context, ILogger logger) { _context = context; _logger = logger; } public async Task DeactivateTokenBySessionAsync(Guid sessionId) { try { await _context.UserPushTokens .Where(t => t.UserSessionId == sessionId && t.IsActive) .ExecuteUpdateAsync(s => s.SetProperty(t => t.IsActive, false)); return Result.Success(); } catch (Exception ex) { _logger.LogError(ex, "Failed to deactivate push token for session {SessionId}", sessionId); return Result.Failure(ex); } } public async Task DeactivateAllTokensByUserIdAsync(Guid userId) { try { await _context.UserPushTokens .Where(t => t.UserId == userId && t.IsActive) .ExecuteUpdateAsync(s => s.SetProperty(t => t.IsActive, false)); return Result.Success(); } catch (Exception ex) { _logger.LogError(ex, "Failed to deactivate all push tokens for user {UserId}", userId); return Result.Failure(ex); } } public async Task>> GetStringsActiveTokensAsync(Guid userId) { try { var tokens = await _context.UserPushTokens .AsNoTracking() .Where(t => t.UserId == userId && t.IsActive) .Select(t => t.Token) .ToListAsync(); return tokens; } catch (Exception ex) { _logger.LogError(ex, "Failed to fetch active push tokens for user {UserId}", userId); return Result>.Failure(ex); } } public async Task>> GetUsersStringsActiveTokensAsync(IEnumerable userIds) { try { var tokens = await _context.UserPushTokens .AsNoTracking() .Where(t => userIds.Contains(t.UserId) && t.IsActive) .Select(t => t.Token) .ToListAsync(); return tokens; } catch (Exception ex) { _logger.LogError(ex, "Failed to fetch active push tokens for bulk users"); return Result>.Failure(ex); } } public async Task> GetActiveTokenBySessionAsync(Guid sessionId) { try { var token = await _context.UserPushTokens .AsNoTracking() .Where(t => t.UserSessionId == sessionId && t.IsActive) .Select(t => t.Token) .FirstOrDefaultAsync(); return token; } catch (Exception ex) { _logger.LogError(ex, "Failed to fetch active push token for session {SessionId}", sessionId); return Result.Failure(ex); } } public async Task RemoveTokensAsync(IEnumerable tokens) { if (tokens is null || !tokens.Any()) return Result.Success(); try { await _context.UserPushTokens .Where(t => tokens.Contains(t.Token)) .ExecuteDeleteAsync(); return Result.Success(); } catch (Exception ex) { _logger.LogError(ex, "Failed to bulk remove invalid push tokens"); return Result.Failure(ex); } } public async Task AddOrUpdateTokenAsync(Guid userId, Guid sessionId, string token, string platform) { if (string.IsNullOrWhiteSpace(token)) { return new Error("PushToken.Empty", "Push token cannot be empty."); } var existingToken = await _context.UserPushTokens .FirstOrDefaultAsync(t => t.Token == token); if (existingToken is null) { var newToken = new UserPushToken { Id = Guid.NewGuid(), UserId = userId, UserSessionId = sessionId, Token = token, Platform = platform, CreatedAt = DateTime.UtcNow }; await _context.UserPushTokens.AddAsync(newToken); } else { existingToken.UserId = userId; existingToken.UserSessionId = sessionId; existingToken.Platform = platform; existingToken.UpdatedAt = DateTime.UtcNow; } await _context.SaveChangesAsync(); return Result.Success(); } }