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
}