namespace Application.Admin.Queries;

using Application.Admin.DTOs;
using Domain.Ports.Repositories;
using MediatR;

public record GetAdminStatsQuery : IRequest<AdminStatsDto>;

public class GetAdminStatsHandler(
    IStudentRepository studentRepository,
    ISubjectRepository subjectRepository)
    : IRequestHandler<GetAdminStatsQuery, AdminStatsDto>
{
    public async Task<AdminStatsDto> Handle(GetAdminStatsQuery request, CancellationToken ct)
    {
        var students = await studentRepository.GetAllWithEnrollmentsAsync(ct);
        var totalStudents = students.Count;

        var totalEnrollments = students.Sum(s => s.Enrollments.Count);

        var avgCredits = totalStudents > 0
            ? students.Average(s => s.Enrollments.Sum(e => e.Subject?.Credits ?? 3))
            : 0;

        var subjects = await subjectRepository.GetAllWithProfessorsAsync(ct);

        var enrollmentCounts = students
            .SelectMany(s => s.Enrollments)
            .GroupBy(e => e.SubjectId)
            .ToDictionary(g => g.Key, g => g.Count());

        var subjectStats = subjects
            .Select(s => new SubjectStatsDto(
                s.Id,
                s.Name,
                s.Professor?.Name ?? "Sin profesor",
                enrollmentCounts.GetValueOrDefault(s.Id, 0)))
            .OrderByDescending(s => s.EnrollmentCount)
            .ToList();

        var mostPopular = subjectStats.FirstOrDefault();

        return new AdminStatsDto(
            totalStudents,
            totalEnrollments,
            Math.Round(avgCredits, 1),
            mostPopular,
            subjectStats);
    }
}
