namespace CMSMicroservice.Application.NetworkMembershipCQ.Commands.JoinNetwork;

public class JoinNetworkCommandHandler : IRequestHandler<JoinNetworkCommand, long>
{
    private readonly IApplicationDbContext _context;
    private readonly ICurrentUserService _currentUser;

    public JoinNetworkCommandHandler(
        IApplicationDbContext context,
        ICurrentUserService currentUser)
    {
        _context = context;
        _currentUser = currentUser;
    }

    public async Task<long> Handle(JoinNetworkCommand request, CancellationToken cancellationToken)
    {
        // بررسی وجود کاربر
        var user = await _context.Users
            .FirstOrDefaultAsync(x => x.Id == request.UserId, cancellationToken);

        if (user == null)
        {
            throw new NotFoundException(nameof(User), request.UserId);
        }

        // بررسی اینکه کاربر قبلاً در شبکه نباشد
        if (user.NetworkParentId.HasValue)
        {
            throw new InvalidOperationException($"کاربر با شناسه {request.UserId} قبلاً در شبکه عضو شده است");
        }

        // بررسی وجود والد
        var parent = await _context.Users
            .FirstOrDefaultAsync(x => x.Id == request.ParentId, cancellationToken);

        if (parent == null)
        {
            throw new NotFoundException(nameof(User), $"Parent with Id {request.ParentId}");
        }

        // بررسی والد خودش در شبکه باشد (یا Root باشد)
        if (!parent.NetworkParentId.HasValue && parent.Id != 1) // فرض: UserId=1 همیشه Root
        {
            throw new InvalidOperationException($"والد با شناسه {request.ParentId} خودش در شبکه عضو نیست");
        }

        // بررسی خالی بودن Leg موردنظر
        var legOccupied = await _context.Users
            .AnyAsync(x => x.NetworkParentId == request.ParentId && x.LegPosition == request.LegPosition,
                cancellationToken);

        if (legOccupied)
        {
            throw new InvalidOperationException(
                $"موقعیت {request.LegPosition} زیر والد {request.ParentId} قبلاً پر شده است");
        }

        // افزودن به شبکه
        user.NetworkParentId = request.ParentId;
        user.LegPosition = request.LegPosition;

        _context.Users.Update(user);
        await _context.SaveChangesAsync(cancellationToken);

        // ثبت تاریخچه
        var history = new NetworkMembershipHistory
        {
            UserId = request.UserId,
            OldParentId = null,
            NewParentId = request.ParentId,
            OldLegPosition = null,
            NewLegPosition = request.LegPosition,
            Action = NetworkMembershipAction.Join,
            Reason = request.Reason ?? "عضویت در شبکه",
            PerformedBy = _currentUser.GetPerformedBy()
        };

        await _context.NetworkMembershipHistories.AddAsync(history, cancellationToken);
        await _context.SaveChangesAsync(cancellationToken);

        return user.Id;
    }
}
