# 🌳 Binary Tree Network Registration Guide

## 📋 Overview

از این پس، هر کاربر جدید که در سیستم ثبت می‌شود، **هم‌زمان** در دو ساختار قرار می‌گیرد:

1. **Old System**: `User.ParentId` (برای Backward Compatibility)
2. **New Binary Tree System**: `User.NetworkParentId` + `User.LegPosition` (Left/Right)

این تغییر تضمین می‌کند که:
- ✅ کاربران جدید بلافاصله در محاسبات Commission شرکت می‌کنند
- ✅ نیازی به Migration اضافی نیست
- ✅ Binary Tree Constraint رعایت می‌شود (حداکثر 2 فرزند)

---

## 🔧 Changes in Registration Flow

### قبل از تغییر:

```csharp
var entity = request.Adapt<User>();
entity.ReferralCode = UtilExtensions.Generate(digits: 10);
await _context.Users.AddAsync(entity, cancellationToken);
```

**مشکل**: فقط `ParentId` Set می‌شد، `NetworkParentId` و `LegPosition` خالی می‌ماند.

---

### بعد از تغییر:

```csharp
var entity = request.Adapt<User>();
entity.ReferralCode = UtilExtensions.Generate(digits: 10);

// === محاسبه موقعیت در Binary Tree ===
if (request.ParentId.HasValue)
{
    var legPosition = await _networkPlacementService.CalculateLegPositionAsync(
        request.ParentId.Value, cancellationToken);

    if (legPosition.HasValue)
    {
        entity.NetworkParentId = request.ParentId.Value;
        entity.LegPosition = legPosition.Value; // Left یا Right
    }
    else
    {
        // Parent پر است! Auto-Placement یا Error
        var availableParent = await _networkPlacementService.FindAvailableParentAsync(
            request.ParentId.Value, cancellationToken);
        
        // ... Set کردن NetworkParentId و LegPosition با Parent جدید
    }
}

await _context.Users.AddAsync(entity, cancellationToken);
```

**مزایا**:
- ✅ `NetworkParentId` و `LegPosition` به صورت خودکار محاسبه می‌شود
- ✅ Binary Tree Constraint چک می‌شود
- ✅ اگر Parent پر باشد، Auto-Placement انجام می‌شود

---

## 📐 Binary Tree Logic

### قوانین:
1. هر Parent فقط **2 فرزند** می‌تواند داشته باشد (Left & Right)
2. فرزند اول: `LegPosition = Left`
3. فرزند دوم: `LegPosition = Right`
4. اگر Parent پر باشد، سیستم به صورت BFS دنبال Parent خالی می‌گردد

### مثال:

```
        User1 (Root)
        /          \
    User2 (L)    User3 (R)
    /      \
User4(L)  User5(R)
```

- User2 → Parent=User1, Leg=Left
- User3 → Parent=User1, Leg=Right
- User4 → Parent=User2, Leg=Left
- User5 → Parent=User2, Leg=Right

اگر کاربر جدید با `ParentId=User1` بیاید:
- User1 پر است! (دو فرزند دارد)
- سیستم به User2 می‌رود (BFS)
- User2 هم پر است!
- به User3 می‌رود → User3 خالی است
- کاربر جدید → Parent=User3, Leg=Left

---

## 🛠️ NetworkPlacementService API

### 1. CalculateLegPositionAsync
محاسبه موقعیت (Left/Right) برای کاربر جدید زیر یک Parent مشخص.

```csharp
var legPosition = await _networkPlacementService.CalculateLegPositionAsync(parentId);
```

**Return Values**:
- `NetworkLeg.Left`: اگر Parent فرزند چپ ندارد
- `NetworkLeg.Right`: اگر Parent فرزند راست ندارد
- `null`: اگر Parent پر است (دو فرزند دارد)

---

### 2. CanAcceptChildAsync
بررسی اینکه آیا Parent می‌تواند فرزند جدید بپذیرد.

```csharp
bool canAccept = await _networkPlacementService.CanAcceptChildAsync(parentId);
```

**Return Values**:
- `true`: اگر Parent کمتر از 2 فرزند دارد
- `false`: اگر Parent پر است

---

### 3. FindAvailableParentAsync (Auto-Placement)
پیدا کردن اولین Parent خالی در Binary Tree با استفاده از BFS.

```csharp
long? availableParentId = await _networkPlacementService.FindAvailableParentAsync(rootParentId);
```

**Use Case**:
- زمانی که Parent مورد نظر پر است
- سیستم به صورت خودکار Parent جایگزین پیدا می‌کند
- از BFS استفاده می‌کند (Level-by-Level)

**Return Values**:
- `long`: شناسه Parent مناسب
- `null`: اگر هیچ Parent خالی پیدا نشد (تمام Binary Tree پر است!)

---

## ⚠️ Error Handling

### Scenario 1: Parent پر است و Auto-Placement موفق

```csharp
// Parent اصلی پر است
// سیستم Parent جدید پیدا می‌کند
_logger.LogWarning("Parent {ParentId} is full. Auto-placing under {NewParentId}");
```

**نتیجه**: کاربر با موفقیت در جای دیگری قرار می‌گیرد.

---

### Scenario 2: کل Binary Tree پر است

```csharp
throw new InvalidOperationException(
    $"شبکه Parent با شناسه {parentId} پر است و نمی‌تواند کاربر جدید بپذیرد.");
```

**نتیجه**: Exception پرتاب می‌شود، ثبت کاربر انجام نمی‌شود.

**راه حل**:
- افزایش سطح Binary Tree
- یا تخصیص دستی Parent

---

### Scenario 3: Parent وجود ندارد

```csharp
var parentExists = await _context.Users.AnyAsync(u => u.Id == parentId);
if (!parentExists)
{
    return null; // Parent نامعتبر
}
```

**نتیجه**: `null` برگردانده می‌شود، Exception پرتاب می‌شود.

---

## 📊 Logging & Monitoring

سیستم Log های زیر را می‌نویسد:

### Success:
```
User 123 placed in Binary Tree: Parent=45, Leg=Left
```

### Warning (Auto-Placement):
```
Parent 45 has no available leg! Finding alternative parent...
User 123 auto-placed under alternative Parent=67, Leg=Right
```

### Error (Binary Tree Full):
```
No available parent found in network for ParentId=45
```

---

## 🧪 Testing Scenarios

### Test 1: کاربر اول (Root)
```csharp
var command = new CreateNewUserCommand { Mobile = "09121234567" }; // No ParentId
// Result: ParentId=null, NetworkParentId=null, LegPosition=null
```

---

### Test 2: فرزند اول
```csharp
var command = new CreateNewUserCommand { Mobile = "09121234568", ParentId = 1 };
// Result: ParentId=1, NetworkParentId=1, LegPosition=Left
```

---

### Test 3: فرزند دوم
```csharp
var command = new CreateNewUserCommand { Mobile = "09121234569", ParentId = 1 };
// Result: ParentId=1, NetworkParentId=1, LegPosition=Right
```

---

### Test 4: فرزند سوم (Parent پر است)
```csharp
var command = new CreateNewUserCommand { Mobile = "09121234570", ParentId = 1 };
// Result: Auto-Placement → ParentId=1, NetworkParentId=2 (یا 3), LegPosition=Left
```

---

## 🔗 Related Files

- **Service Interface**: `CMSMicroservice.Application/Common/Interfaces/INetworkPlacementService.cs`
- **Service Implementation**: `CMSMicroservice.Infrastructure/Services/NetworkPlacementService.cs`
- **Handler**: `CMSMicroservice.Application/UserCQ/Commands/CreateNewUser/CreateNewUserCommandHandler.cs`
- **DI Registration**: `CMSMicroservice.Infrastructure/ConfigureServices.cs` (خط 23)

---

## ✅ Checklist

- [x] `INetworkPlacementService` اضافه شد
- [x] `NetworkPlacementService` پیاده‌سازی شد
- [x] DI Container تنظیم شد
- [x] `CreateNewUserCommandHandler` اصلاح شد
- [ ] Unit Tests نوشته شود
- [ ] Integration Tests انجام شود
- [ ] Manual Testing با Postman/gRPC Client

---

## 🚀 Next Steps

1. **Test کردن**: ثبت چند کاربر با Parent مشابه و بررسی LegPosition
2. **Load Testing**: بررسی Performance با 10,000 کاربر
3. **Edge Cases**: تست Binary Tree Full scenario
4. **Documentation**: Update کردن API Docs

---

## 📞 Support

اگر مشکلی پیش آمد:
- Log های `NetworkPlacementService` را بررسی کنید
- چک کنید که DI به درستی تنظیم شده باشد
- از `CanAcceptChildAsync` برای Pre-Validation استفاده کنید
