namespace CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubStatistics;

public class GetClubStatisticsQueryHandler : IRequestHandler<GetClubStatisticsQuery, GetClubStatisticsResponseDto>
{
    private readonly IApplicationDbContext _context;

    public GetClubStatisticsQueryHandler(IApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<GetClubStatisticsResponseDto> Handle(GetClubStatisticsQuery request, CancellationToken cancellationToken)
    {
        var now = DateTime.Now;

        // Basic statistics
        var totalMembers = await _context.ClubMemberships.CountAsync(cancellationToken);
        
        var activeMembers = await _context.ClubMemberships
            .Where(x => x.IsActive)
            .CountAsync(cancellationToken);

        var inactiveMembers = totalMembers - activeMembers;
        var expiredMembers = 0; // Since there's no expiration tracking in the model

        double activePercentage = totalMembers > 0 ? (activeMembers / (double)totalMembers) * 100 : 0;

        // Package distribution - ClubMembership doesn't have PackageId
        // We'll return empty list for now or create mock data
        var packageDistribution = new List<PackageLevelDistributionModel>();

        // Monthly trend (last 6 months)
        var sixMonthsAgo = now.AddMonths(-6);
        
        var activations = await _context.ClubMemberships
            .Where(x => x.ActivatedAt >= sixMonthsAgo && x.ActivatedAt != null)
            .GroupBy(x => new { x.ActivatedAt!.Value.Year, x.ActivatedAt.Value.Month })
            .Select(g => new { g.Key.Year, g.Key.Month, Count = g.Count() })
            .ToListAsync(cancellationToken);

        var monthlyTrend = new List<MonthlyMembershipTrendModel>();
        for (int i = 5; i >= 0; i--)
        {
            var targetDate = now.AddMonths(-i);
            var year = targetDate.Year;
            var month = targetDate.Month;

            var activationCount = activations.FirstOrDefault(x => x.Year == year && x.Month == month)?.Count ?? 0;

            monthlyTrend.Add(new MonthlyMembershipTrendModel
            {
                Month = $"{year}-{month:D2}",
                Activations = activationCount,
                Expirations = 0, // No expiration tracking
                NetChange = activationCount
            });
        }

        // Total revenue - sum of initial contributions
        var totalRevenue = await _context.ClubMemberships
            .SumAsync(x => x.InitialContribution, cancellationToken);

        // Average membership duration - calculate from ActivatedAt to now
        var activeMemberships = await _context.ClubMemberships
            .Where(x => x.IsActive && x.ActivatedAt != null)
            .Select(x => x.ActivatedAt!.Value)
            .ToListAsync(cancellationToken);

        double averageDuration = 0;
        if (activeMemberships.Any())
        {
            var durations = activeMemberships
                .Select(activatedAt => (now - activatedAt).TotalDays)
                .ToList();
            averageDuration = durations.Average();
        }

        // Expiring soon count - not applicable since no expiration tracking
        int expiringSoonCount = 0;

        return new GetClubStatisticsResponseDto
        {
            TotalMembers = totalMembers,
            ActiveMembers = activeMembers,
            InactiveMembers = inactiveMembers,
            ExpiredMembers = expiredMembers,
            ActivePercentage = activePercentage,
            PackageDistribution = packageDistribution,
            MonthlyTrend = monthlyTrend,
            TotalRevenue = totalRevenue,
            AverageMembershipDurationDays = averageDuration,
            ExpiringSoonCount = expiringSoonCount
        };
    }
}
