// EN: Handler for CancelAppointmentCommand.
// VI: Handler cho CancelAppointmentCommand.

using BookingService.Domain.Exceptions;
using BookingService.Infrastructure.Repositories;
using MediatR;

namespace BookingService.API.Application.Commands;

/// <summary>
/// EN: Handler for cancelling appointments.
/// VI: Handler để hủy cuộc hẹn.
/// </summary>
public class CancelAppointmentCommandHandler : IRequestHandler<CancelAppointmentCommand, bool>
{
    private readonly IAppointmentRepository _appointmentRepository;
    private readonly ILogger<CancelAppointmentCommandHandler> _logger;

    public CancelAppointmentCommandHandler(
        IAppointmentRepository appointmentRepository,
        ILogger<CancelAppointmentCommandHandler> logger)
    {
        _appointmentRepository = appointmentRepository ?? throw new ArgumentNullException(nameof(appointmentRepository));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<bool> Handle(CancelAppointmentCommand request, CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "Cancelling appointment {AppointmentId} with reason: {Reason}",
            request.AppointmentId, request.Reason);

        // EN: Load appointment from repository
        // VI: Load appointment từ repository
        var appointment = await _appointmentRepository.GetByIdAsync(request.AppointmentId, cancellationToken);
        if (appointment == null)
        {
            throw new DomainException($"Appointment {request.AppointmentId} not found");
        }

        // EN: Call domain method to cancel
        // VI: Gọi domain method để hủy
        appointment.Cancel(request.Reason);

        // EN: Save changes
        // VI: Lưu thay đổi
        _appointmentRepository.Update(appointment);
        await _appointmentRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation("Cancelled appointment {AppointmentId}", appointment.Id);

        return true;
    }
}
