using CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkTree;
using CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetUserNetworkPosition;
using CMSMicroservice.Application.NetworkMembershipCQ.Queries.GetNetworkStatistics;
using CMSMicroservice.Protobuf.Protos.NetworkMembership;
using CMSMicroservice.Domain.Enums;

namespace CMSMicroservice.WebApi.Common.Mappings;

public class NetworkMembershipProfile : IRegister
{
    void IRegister.Register(TypeAdapterConfig config)
    {
        // GetNetworkStatisticsRequest -> GetNetworkStatisticsQuery
        config.NewConfig<GetNetworkStatisticsRequest, GetNetworkStatisticsQuery>()
            .MapWith(src => new GetNetworkStatisticsQuery());

        // Request mapping
        config.NewConfig<GetNetworkTreeRequest, GetNetworkTreeQuery>()
            .Map(dest => dest.UserId, src => src.UserId)
            .Map(dest => dest.MaxDepth, src => src.MaxDepth != null && src.MaxDepth.Value > 0 ? src.MaxDepth.Value : 3)
            .Map(dest => dest.IsClubActive, src => src.IsClubActive)
            .Map(dest => dest.ActivationWeekDefinitionId, src => src.ActivationWeekDefinitionId);

        // Response mapping: تبدیل درخت به لیست مسطح
        config.NewConfig<NetworkTreeDto, GetNetworkTreeResponse>()
            .MapWith(src => ConvertTreeToResponse(src));      
        
        
        config.NewConfig<UserNetworkPositionDto, GetUserNetworkResponse>()
            .Map(dest => dest.Id, src => src.UserId)
            .Map(dest => dest.UserId, src => src.UserId)
            .Map(dest => dest.UserName, src => (src.FirstName + " " + src.LastName).Trim())
            .Map(dest => dest.Mobile, src => src.Mobile ?? "")
            .Map(dest => dest.Email, src => src.Email ?? "")
            .Map(dest => dest.NationalCode, src => src.NationalCode ?? "")
            .Map(dest => dest.ReferralCode, src => src.ReferralCode)
            .Map(dest => dest.IsMobileVerified, src => src.IsMobileVerified)
            .Map(dest => dest.ParentId, src => src.NetworkParentId)
            .Map(dest => dest.ParentName, src => src.ParentFullName ?? "")
            .Map(dest => dest.ParentMobile, src => src.ParentMobile ?? "")
            .Map(dest => dest.NetworkLeg, src => (int)(src.LegPosition ?? NetworkLeg.Left))
            .Map(dest => dest.NetworkLevel, src => 0) // Deprecated field
            .Map(dest => dest.IsInNetwork, src => src.IsInNetwork)
            .Map(dest => dest.LeftChildId, src => src.LeftChildId)
            .Map(dest => dest.LeftChildName, src => src.LeftChildFullName ?? "")
            .Map(dest => dest.LeftChildMobile, src => src.LeftChildMobile ?? "")
            .Map(dest => dest.RightChildId, src => src.RightChildId)
            .Map(dest => dest.RightChildName, src => src.RightChildFullName ?? "")
            .Map(dest => dest.RightChildMobile, src => src.RightChildMobile ?? "")
            .Map(dest => dest.TotalChildren, src => src.TotalChildren)
            .Map(dest => dest.LeftChildCount, src => src.LeftChildCount)
            .Map(dest => dest.RightChildCount, src => src.RightChildCount)
            .Map(dest => dest.TotalLeftLegMembers, src => src.TotalLeftLegMembers)
            .Map(dest => dest.TotalRightLegMembers, src => src.TotalRightLegMembers)
            .Map(dest => dest.TotalNetworkSize, src => src.TotalNetworkSize)
            .Map(dest => dest.MaxNetworkDepth, src => src.MaxNetworkDepth)
            .Map(dest => dest.HasReceivedDayaCredit, src => src.HasReceivedDayaCredit)
            .Map(dest => dest.PackagePurchaseMethod, src => (int)src.PackagePurchaseMethod)
            .Map(dest => dest.HasPurchasedPackage, src => src.HasPurchasedPackage)
            .Map(dest => dest.TotalEarnedCommission, src => (double)src.TotalEarnedCommission)
            .Map(dest => dest.TotalPaidCommission, src => (double)src.TotalPaidCommission)
            .Map(dest => dest.PendingCommission, src => (double)src.PendingCommission)
            .Map(dest => dest.TotalBalancesEarned, src => src.TotalBalancesEarned)
            .Map(dest => dest.ActiveMembersInNetwork, src => src.ActiveMembersInNetwork)
            .Map(dest => dest.InactiveMembersInNetwork, src => src.InactiveMembersInNetwork);
    }

    private static GetNetworkTreeResponse ConvertTreeToResponse(NetworkTreeDto? treeDto)
    {
        var response = new GetNetworkTreeResponse();
        
        if (treeDto == null)
        {
            return response;
        }

        // تبدیل درخت به لیست مسطح
        FlattenTree(treeDto, response.Nodes, null);
        
        return response;
    }

    private static void FlattenTree(NetworkTreeDto node, Google.Protobuf.Collections.RepeatedField<NetworkTreeNodeModel> nodesList, long? parentId)
    {
        var protoNode = new NetworkTreeNodeModel
        {
            UserId = node.UserId,
            UserName = $"{node.FirstName} {node.LastName}".Trim(),
            ReferralCode = node.ReferralCode ?? string.Empty,
            NetworkLeg = (int)(node.LegPosition ?? NetworkLeg.Left),
            NetworkLevel = node.CurrentDepth,
            IsActive = true,
            IsClubActive = node.IsClubActive,
            ActivationWeekDefinitionId = node.ActivationWeekDefinitionId ?? 0,
            IsActivatedInTargetWeek = node.IsActivatedInTargetWeek,
            PackageName = node.PackageName ?? string.Empty,
            PackageId = node.PackageId.HasValue ? node.PackageId.Value : null,
            IsNewActivation = node.IsNewActivation.HasValue ? node.IsNewActivation.Value : null,
            GoldLeftLegTotal = node.GoldLeftLegTotal,
            GoldRightLegTotal = node.GoldRightLegTotal,
            SilverLeftLegTotal = node.SilverLeftLegTotal,
            SilverRightLegTotal = node.SilverRightLegTotal
        };

        if (parentId.HasValue)
        {
            protoNode.ParentId = parentId.Value;
        }

        // تبدیل تاریخ فعال‌سازی باشگاه
        if (node.ClubActivatedAt.HasValue)
        {
            protoNode.ClubActivatedAt = Timestamp.FromDateTime(
                DateTime.SpecifyKind(node.ClubActivatedAt.Value, DateTimeKind.Utc));
        }

        // تبدیل تاریخ ایجاد کاربر
        protoNode.UserCreated = Timestamp.FromDateTimeOffset(node.UserCreated);

        nodesList.Add(protoNode);

        // بازگشتی برای فرزندان
        if (node.LeftChild != null)
        {
            FlattenTree(node.LeftChild, nodesList, node.UserId);
        }

        if (node.RightChild != null)
        {
            FlattenTree(node.RightChild, nodesList, node.UserId);
        }
    }
}
