using CMSMicroservice.Protobuf.Protos.NetworkMembership; using Google.Protobuf.WellKnownTypes; namespace FrontOffice.Main.Utilities; /// /// Service for Network Membership operations /// Connected to FrontOffice.BFF gRPC NetworkMembershipCQ /// public class NetworkMembershipService { private readonly NetworkMembershipContract.NetworkMembershipContractClient _client; public NetworkMembershipService(NetworkMembershipContract.NetworkMembershipContractClient client) { _client = client; } /// /// Get current user's network tree /// Maps to: NetworkMembershipCQ.GetMyNetworkTree /// public async Task GetMyNetworkTreeAsync(int maxDepth = 3) { try { var request = new GetMyNetworkTreeRequest { MaxDepth = maxDepth }; var response = await _client.GetMyNetworkTreeAsync(request); return new NetworkTreeDto { RootNode = MapNodeFromProto(response.RootNode), TotalMembers = response.TotalMembers, CurrentDepth = response.CurrentDepth }; } catch { // Return empty tree if backend is unavailable return new NetworkTreeDto { CurrentDepth = 0, TotalMembers = 0, RootNode = null }; } } /// /// Get subordinate's network tree (with security check on backend) /// Maps to: NetworkMembershipCQ.GetSubordinateTree /// public async Task GetSubordinateTreeAsync(long targetUserId, int maxDepth = 3) { try { var request = new GetSubordinateTreeRequest { TargetUserId = targetUserId, MaxDepth = maxDepth }; var response = await _client.GetSubordinateTreeAsync(request); return new NetworkTreeDto { RootNode = MapNodeFromProto(response.RootNode), TotalMembers = response.TotalMembers, CurrentDepth = response.CurrentDepth }; } catch (Grpc.Core.RpcException ex) when (ex.StatusCode == Grpc.Core.StatusCode.PermissionDenied) { throw new UnauthorizedAccessException("شما اجازه مشاهده درخت این کاربر را ندارید"); } catch { // Fallback to current user's tree return await GetMyNetworkTreeAsync(maxDepth); } } /// /// Get current user's network statistics /// Maps to: NetworkMembershipCQ.GetMyNetworkStatistics /// public async Task GetMyNetworkStatisticsAsync() { try { var response = await _client.GetMyNetworkStatisticsAsync(new Empty()); return new NetworkStatisticsDto { LeftLegCount = response.LeftLegCount, RightLegCount = response.RightLegCount, TotalMembers = response.TotalMembers, TreeDepth = response.MaxDepth, WeakerLeg = response.WeakerLeg, LastMember = response.LastMember != null ? new LastMemberDto { UserId = response.LastMember.UserId, FullName = response.LastMember.FullName, Position = response.LastMember.Position, JoinedAt = DateTime.Now // TODO: Add JoinedAt to proto } : null }; } catch { // Return empty statistics if backend is unavailable return new NetworkStatisticsDto { LeftLegCount = 0, RightLegCount = 0, TotalMembers = 0, TreeDepth = 0, WeakerLeg = string.Empty, LastMember = null }; } } #region Helper Methods private static NetworkNodeDto? MapNodeFromProto(NetworkTreeNodeModel? node) { if (node == null) return null; return new NetworkNodeDto { UserId = node.UserId, FullName = node.FullName, Mobile = node.Mobile, Avatar = node.Avatar, Position = node.Position, Level = node.Level, IsActive = node.IsActive, IsClubActive = node.IsClubActive, ReferralCode = node.ReferralCode, PackageName = string.IsNullOrWhiteSpace(node.PackageName) ? null : node.PackageName, ActivationWeekNumber = node.ActivationWeekDefinitionId?.ToString(), JoinedAt = node.JoinedAt?.ToDateTime(), LeftChild = MapNodeFromProto(node.LeftChild), RightChild = MapNodeFromProto(node.RightChild) }; } #endregion }