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

using BookingService.API.Application.DTOs;
using BookingService.Domain.Exceptions;
using BookingService.Infrastructure.Repositories;
using MediatR;

namespace BookingService.API.Application.Commands;

/// <summary>
/// EN: Handler for marking an appointment as no-show.
/// VI: Handler để đánh dấu cuộc hẹn là không đến.
/// </summary>
public class MarkNoShowCommandHandler : IRequestHandler<MarkNoShowCommand, AppointmentDto>
{
    private readonly IAppointmentRepository _appointmentRepository;
    private readonly ILogger<MarkNoShowCommandHandler> _logger;

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

    public async Task<AppointmentDto> Handle(MarkNoShowCommand request, CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "Marking appointment {AppointmentId} as no-show / Đánh dấu cuộc hẹn {AppointmentId} là không đến",
            request.AppointmentId);

        // EN: Load appointment from repository
        // VI: Load cuộc hẹn từ repository
        var appointment = await _appointmentRepository.GetByIdAsync(request.AppointmentId, cancellationToken);
        if (appointment == null)
        {
            throw new DomainException($"Appointment {request.AppointmentId} not found / Không tìm thấy cuộc hẹn {request.AppointmentId}");
        }

        // EN: Mark as no-show via domain behavior
        // VI: Đánh dấu không đến qua hành vi domain
        appointment.MarkNoShow();

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

        _logger.LogInformation(
            "Marked appointment {AppointmentId} as NoShow / Đã đánh dấu cuộc hẹn {AppointmentId} là không đến",
            appointment.Id);

        return new AppointmentDto
        {
            Id = appointment.Id,
            ShopId = appointment.ShopId,
            CustomerId = appointment.CustomerId,
            StaffId = appointment.StaffId,
            ResourceId = appointment.ResourceId,
            ServiceId = appointment.ServiceId,
            StartTime = appointment.StartTime,
            EndTime = appointment.EndTime,
            Status = appointment.Status,
            Notes = appointment.Notes,
            CreatedAt = appointment.CreatedAt
        };
    }
}
