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

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

namespace BookingService.API.Application.Commands;

/// <summary>
/// EN: Handler for updating appointment status.
/// VI: Handler để cập nhật trạng thái cuộc hẹn.
/// </summary>
public class UpdateAppointmentStatusCommandHandler : IRequestHandler<UpdateAppointmentStatusCommand, AppointmentDto>
{
    private readonly IAppointmentRepository _appointmentRepository;
    private readonly ILogger<UpdateAppointmentStatusCommandHandler> _logger;

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

    public async Task<AppointmentDto> Handle(UpdateAppointmentStatusCommand request, CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "Updating appointment {AppointmentId} status with action {Action}",
            request.AppointmentId, request.Action);

        // 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: Execute domain action based on request
        // VI: Thực hiện domain action dựa trên request
        switch (request.Action.ToLowerInvariant())
        {
            case "confirm":
                appointment.Confirm();
                break;
            case "start":
                appointment.MarkAsInProgress();
                break;
            case "complete":
                appointment.Complete();
                break;
            default:
                throw new DomainException($"Invalid action: {request.Action}");
        }

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

        _logger.LogInformation(
            "Updated appointment {AppointmentId} to status {Status}",
            appointment.Id, appointment.Status);

        // EN: Return updated DTO
        // VI: Trả về DTO đã cập nhật
        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,
            CreatedAt = appointment.CreatedAt
        };
    }
}
