namespace Application.Enrollments.Commands;

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

public record EnrollStudentCommand(int StudentId, int SubjectId) : IRequest<EnrollmentDto>;

public class EnrollStudentHandler(
    IStudentRepository studentRepository,
    ISubjectRepository subjectRepository,
    IEnrollmentRepository enrollmentRepository,
    EnrollmentDomainService enrollmentService,
    IUnitOfWork unitOfWork)
    : IRequestHandler<EnrollStudentCommand, EnrollmentDto>
{
    public async Task<EnrollmentDto> Handle(EnrollStudentCommand request, CancellationToken ct)
    {
        var student = await studentRepository.GetByIdWithEnrollmentsAsync(request.StudentId, ct)
            ?? throw new StudentNotFoundException(request.StudentId);

        var subject = await subjectRepository.GetByIdWithProfessorAsync(request.SubjectId, ct)
            ?? throw new SubjectNotFoundException(request.SubjectId);

        var enrollment = enrollmentService.CreateEnrollment(student, subject);
        enrollmentRepository.Add(enrollment);
        await unitOfWork.SaveChangesAsync(ct);

        return new EnrollmentDto(
            enrollment.Id,
            subject.Id,
            subject.Name,
            subject.Credits,
            subject.Professor?.Name ?? "",
            enrollment.EnrolledAt);
    }
}
