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 ContactDto( Guid Id, string Username, string DisplayName, string Avatar, bool IsOnline, DateTime? LastSeen, Guid RelationId, bool IsBlocked = false, bool IsExternal = false, string? Domain = null); 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) { var relations = await _context.Contacts .Where(c => (c.UserId == request.UserId || c.ContactId == request.UserId) && c.Status == ContactStatus.Accepted) .ToListAsync(cancellationToken); var contactIds = relations.Select(c => c.UserId == request.UserId ? c.ContactId : c.UserId).ToList(); var replicas = await _context.UserReplicas .Where(r => contactIds.Contains(r.Id)) .ToListAsync(cancellationToken); var result = new List(); foreach (var replica in replicas) { var rel = relations.First(c => c.UserId == replica.Id || c.ContactId == replica.Id); result.Add(new ContactDto( replica.Id, replica.Username, replica.DisplayName, replica.Avatar, false, // Presence handled by another service or real-time null, rel.Id, rel.Status == ContactStatus.Blocked, replica.IsExternal, replica.Domain )); } return Result.Success(result); } }