using Data.SeaHavenIndustries; using Microsoft.EntityFrameworkCore; using SeaHaven.DataServices.Dto; using SeaHaven.DataServices.Interfaces; namespace SeaHaven.DataServices.Implementation { public class UserDataService : IUserDataService { private readonly ApplicationDbContext _context; public UserDataService(ApplicationDbContext context) { _context = context; } public async Task GetByIdAsync(string id) { return await _context.Users.FindAsync(id); } public async Task> GetAllAsync() { return await _context.Users.ToListAsync(); } public async Task GetByEmailAsync(string email) { return await _context.Users .FirstOrDefaultAsync(u => u.Email == email); } public async Task ExistsAsync(string id) { return await _context.Users.AnyAsync(u => u.Id == id); } public async Task> GetAllForListAsync(CancellationToken cancellationToken) { return await _context.Users .AsNoTracking() .Select(user => new UserListRowData { Id = user.Id, RoleName = ( from userRole in _context.UserRoles join role in _context.Roles on userRole.RoleId equals role.Id where userRole.UserId == user.Id select role.Name).FirstOrDefault() ?? user.PhoneNumber, Email = user.Email, Name = ((user.FirstName ?? "") + " " + (user.LastName ?? "")).Trim(), CreatedDate = user.CreatedDate, Status = user.UniqueName, Phone = user.Contact ?? user.PhoneNumber, Color = user.Color, PendingRegistration = user.PendingRegistration, ServiceAreas = user.ServiceAreas .OrderBy(area => area.Area) .Select(area => area.Area) .ToList() }) .ToListAsync(cancellationToken); } public async Task GetProfileAsync(string id, CancellationToken cancellationToken) { return await _context.Users .AsNoTracking() .Where(u => u.Id == id) .Select(user => new UserProfileData { Id = user.Id, FirstName = user.FirstName, Email = user.Email, Contact = user.Contact, CreatedDate = user.CreatedDate }) .FirstOrDefaultAsync(cancellationToken); } public async Task UpdateProfileAsync( string id, string? name, string? email, string? contact, CancellationToken cancellationToken) { var updated = await _context.Users .Where(user => user.Id == id) .ExecuteUpdateAsync( setters => setters .SetProperty(user => user.FirstName, name) .SetProperty(user => user.Email, email) .SetProperty(user => user.Contact, contact), cancellationToken); return updated == 1; } public async Task GetForEditAsync(string id, CancellationToken cancellationToken) { return await _context.Users .Where(w => w.Id == id) .FirstOrDefaultAsync(cancellationToken); } public async Task IsAccountOwnerAsync(string userId, CancellationToken cancellationToken) { return await _context.Users .AsNoTracking() .Where(user => user.Id == userId) .Select(user => user.IsAccountOwner) .SingleOrDefaultAsync(cancellationToken); } public async Task GetByEmailNormalizedAsync(string email, CancellationToken cancellationToken) { var normalizedEmail = email.Trim().ToUpperInvariant(); return await _context.Users .AsNoTracking() .Where(user => user.NormalizedEmail == normalizedEmail) .FirstOrDefaultAsync(cancellationToken); } public async Task UpdateUserAsync(ApplicationUser user, CancellationToken cancellationToken) { _context.Users.Update(user); await _context.SaveChangesAsync(cancellationToken); } public async Task DeleteUserWithCascadeAsync(ApplicationUser user, CancellationToken cancellationToken) { var id = user.Id; await using var transaction = await _context.Database.BeginTransactionAsync(cancellationToken); await _context.workOrders .Where(workOrder => workOrder.AssignTo == id) .ExecuteUpdateAsync( setters => setters.SetProperty(workOrder => workOrder.AssignTo, (string?)null), cancellationToken); await _context.Comments .Where(comment => comment.UserId == id) .ExecuteUpdateAsync( setters => setters.SetProperty(comment => comment.UserId, (string?)null), cancellationToken); await _context.Templates .Where(template => template.AssignTo == id) .ExecuteUpdateAsync( setters => setters.SetProperty(template => template.AssignTo, (string?)null), cancellationToken); await _context.UserRoles .Where(role => role.UserId == id) .ExecuteDeleteAsync(cancellationToken); await _context.Users .Where(existingUser => existingUser.Id == id) .ExecuteDeleteAsync(cancellationToken); await transaction.CommitAsync(cancellationToken); } public async Task GetEmailByIdAsync( string userId, CancellationToken cancellationToken) { return await _context.Users .AsNoTracking() .Where(user => user.Id == userId) .Select(user => user.Email) .FirstOrDefaultAsync(cancellationToken); } public async Task> GetDisplayNamesByIdsAsync(IEnumerable ids) { var idList = ids .Where(id => !string.IsNullOrWhiteSpace(id)) .Distinct(StringComparer.Ordinal) .ToList(); if (idList.Count == 0) return new Dictionary(StringComparer.Ordinal); var users = await _context.Users .AsNoTracking() .Where(u => idList.Contains(u.Id)) .Select(u => new { u.Id, u.FirstName, u.LastName }) .ToListAsync(); return users.ToDictionary( u => u.Id, u => $"{u.FirstName ?? ""} {u.LastName ?? ""}".Trim(), StringComparer.Ordinal); } } }