namespace Application.Students.Commands;

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

public record UpdateStudentCommand(int Id, string Name, string Email) : IRequest<StudentDto>;

public class UpdateStudentHandler(
    IStudentRepository studentRepository,
    IUnitOfWork unitOfWork)
    : IRequestHandler<UpdateStudentCommand, StudentDto>
{
    public async Task<StudentDto> Handle(UpdateStudentCommand request, CancellationToken ct)
    {
        var student = await studentRepository.GetByIdWithEnrollmentsAsync(request.Id, ct)
            ?? throw new StudentNotFoundException(request.Id);

        student.UpdateName(request.Name);
        student.UpdateEmail(Email.Create(request.Email));

        studentRepository.Update(student);
        await unitOfWork.SaveChangesAsync(ct);

        return new StudentDto(
            student.Id,
            student.Name,
            student.Email.Value,
            student.TotalCredits,
            student.Enrollments.Select(e => new EnrollmentDto(
                e.Id,
                e.SubjectId,
                e.Subject?.Name ?? "",
                e.Subject?.Credits ?? 3,
                e.Subject?.Professor?.Name ?? "",
                e.EnrolledAt)).ToList()
        );
    }
}
