namespace Application.Students.Queries;

using Application.Students.DTOs;
using Domain.Entities;
using Domain.Exceptions;
using Domain.Ports.Repositories;
using MediatR;

public record GetStudentByIdQuery(int Id) : IRequest<StudentDto>;

public class GetStudentByIdHandler(IStudentRepository studentRepository)
    : IRequestHandler<GetStudentByIdQuery, StudentDto>
{
    public async Task<StudentDto> Handle(GetStudentByIdQuery request, CancellationToken ct)
    {
        // Direct projection - only SELECT needed columns
        var dto = await studentRepository.GetByIdProjectedAsync(
            request.Id,
            s => new StudentDto(
                s.Id,
                s.Name,
                s.Email.Value,
                s.Enrollments.Sum(e => e.Subject != null ? e.Subject.Credits : Subject.CreditsPerSubject),
                s.Enrollments.Select(e => new EnrollmentDto(
                    e.Id,
                    e.SubjectId,
                    e.Subject != null ? e.Subject.Name : "",
                    e.Subject != null ? e.Subject.Credits : Subject.CreditsPerSubject,
                    e.Subject != null && e.Subject.Professor != null ? e.Subject.Professor.Name : "",
                    e.EnrolledAt)).ToList()
            ), ct);

        return dto ?? throw new StudentNotFoundException(request.Id);
    }
}
