using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Application.Common.Models;

namespace CMSMicroservice.Application.UserCQ.Queries.GetCustomerReferrals;

public class GetCustomerReferralsQueryHandler : IRequestHandler<GetCustomerReferralsQuery, GetCustomerReferralsResponseDto>
{
    private readonly IApplicationDbContext _context;
    private readonly ICurrentUserService _currentUser;

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

    public async Task<GetCustomerReferralsResponseDto> Handle(GetCustomerReferralsQuery request, CancellationToken cancellationToken)
    {
        // Get userId from ICurrentUserService if not provided
        var userId = request.UserId == 0
            ? (long.TryParse(_currentUser.UserId, out var id) ? id : 0)
            : request.UserId;

        if (userId == 0)
            throw new UnauthorizedAccessException("User ID not found in JWT token");

        // Get referrals (children in network)
        var query = _context.Users
            .AsNoTracking()
            .Where(x => x.NetworkParentId == userId);

        // Apply status filter
        if (!string.IsNullOrEmpty(request.StatusFilter))
        {
            if (request.StatusFilter.ToUpper() == "ACTIVE")
                query = query.Where(x => x.IsMobileVerified);
            else if (request.StatusFilter.ToUpper() == "INACTIVE")
                query = query.Where(x => !x.IsMobileVerified);
            // ALL - no additional filter
        }

        query = query.OrderByDescending(x => x.Created);

        // Calculate stats
        var allReferrals = await _context.Users
            .AsNoTracking()
            .Where(x => x.NetworkParentId == userId)
            .ToListAsync(cancellationToken);

        var totalReferrals = allReferrals.Count;
        var activeReferrals = allReferrals.Count(x => x.IsMobileVerified);

        // Calculate commission for current user
        var userWallet = await _context.UserWallets
            .AsNoTracking()
            .Where(x => x.UserId == userId)
            .FirstOrDefaultAsync(cancellationToken);

        var totalCommission = userWallet?.NetworkBalance ?? 0;

        // Calculate this month's commission from wallet changelog
        var startOfMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
        var thisMonthCommission = await _context.UserWalletHistories
            .AsNoTracking()
            .Include(x => x.Wallet)
            .Where(x => x.Wallet.UserId == userId && x.Created >= startOfMonth)
            .SumAsync(x => x.ChangeNerworkValue, cancellationToken);

        // Pagination
        var totalCount = await query.CountAsync(cancellationToken);
        
        var paginationState = request.PaginationState ?? new PaginationState { PageNumber = 1, PageSize = 10 };
        var referrals = await query
            .Skip((paginationState.PageNumber - 1) * paginationState.PageSize)
            .Take(paginationState.PageSize)
            .ToListAsync(cancellationToken);

        var metaData = new MetaData
        {
            TotalCount = totalCount,
            CurrentPage = paginationState.PageNumber,
            PageSize = paginationState.PageSize,
            TotalPage = (int)Math.Ceiling((double)totalCount / paginationState.PageSize),
            HasPrevious = paginationState.PageNumber > 1,
            HasNext = paginationState.PageNumber < (int)Math.Ceiling((double)totalCount / paginationState.PageSize)
        };

        var referralModels = referrals.Select(r => new CustomerReferralModel
        {
            Id = r.Id,
            FirstName = r.FirstName,
            LastName = r.LastName,
            Mobile = r.Mobile,
            JoinDate = r.Created,
            IsActive = r.IsMobileVerified,
            StatusMessage = r.IsMobileVerified ? "Active" : "Inactive",
            Level = 1, // Direct referral
            TotalCommission = 0 // Not tracking per-referral commission
        }).ToList();

        return new GetCustomerReferralsResponseDto
        {
            MetaData = metaData,
            Referrals = referralModels,
            Stats = new CustomerReferralStats
            {
                TotalReferrals = totalReferrals,
                ActiveReferrals = activeReferrals,
                TotalCommissionEarned = totalCommission,
                ThisMonthCommission = thisMonthCommission
            }
        };
    }
}
