using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Knot.Modules.Relations.Domain; using Knot.Shared.Kernel; using Microsoft.EntityFrameworkCore; using Knot.Modules.Relations.Application.Abstractions; namespace Knot.Modules.Relations.Application.Contacts; public record GetContactsQuery(Guid UserId) : IQuery>; internal sealed class GetContactsQueryHandler : IQueryHandler> { private readonly IContactsDbContext _context; public GetContactsQueryHandler(IContactsDbContext context) { _context = context; } public async Task>> Handle(GetContactsQuery request, CancellationToken cancellationToken) { // 1. Fetch ALL accepted relations for current user var relations = await _context.Contacts .Where(c => (c.UserId == request.UserId || c.ContactId == request.UserId) && c.Status == ContactStatus.Accepted) .ToListAsync(cancellationToken); // 2. Fetch all unique IDs for users we need replicas for var contactIds = relations.Select(c => c.UserId == request.UserId ? c.ContactId : c.UserId).Distinct().ToList(); // 3. Fetch replicas var replicas = await _context.UserReplicas .Where(r => contactIds.Contains(r.Id)) .ToDictionaryAsync(r => r.Id, cancellationToken); var result = new List(); // 4. Iterate over RELATIONS (to ensure we don't skip people with missing replicas) foreach (var rel in relations) { var otherUserId = rel.UserId == request.UserId ? rel.ContactId : rel.UserId; if (replicas.TryGetValue(otherUserId, out var replica)) { result.Add(new ContactDto( replica.Id, replica.Username, replica.DisplayName, replica.Avatar, false, // isOnline - current user query doesn't handle this here null, // lastSeen rel.Id, rel.Status == ContactStatus.Blocked, replica.IsExternal, replica.Domain )); } else { // Return placeholder but ensure it's in the list result.Add(new ContactDto( otherUserId, "Unknown", "Unknown", "", false, null, rel.Id, false, false, null )); } } return Result.Success(result); } }