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

using MediatR;
using FnbEngine.Domain.AggregatesModel.TableAggregate;

namespace FnbEngine.API.Application.Commands;

/// <summary>
/// EN: Handler for changing table status.
/// VI: Handler đổi trạng thái bàn.
/// </summary>
public class ChangeTableStatusCommandHandler : IRequestHandler<ChangeTableStatusCommand, bool>
{
    private readonly ITableRepository _tableRepository;
    private readonly ILogger<ChangeTableStatusCommandHandler> _logger;

    public ChangeTableStatusCommandHandler(
        ITableRepository tableRepository,
        ILogger<ChangeTableStatusCommandHandler> logger)
    {
        _tableRepository = tableRepository ?? throw new ArgumentNullException(nameof(tableRepository));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<bool> Handle(ChangeTableStatusCommand request, CancellationToken cancellationToken)
    {
        var table = await _tableRepository.GetByIdAsync(request.TableId, cancellationToken);
        
        if (table == null)
        {
            throw new InvalidOperationException($"Table {request.TableId} not found");
        }

        // EN: Use domain methods to change status
        // VI: Sử dụng domain methods để đổi trạng thái
        switch (request.Status.ToLowerInvariant())
        {
            case "available":
                table.MarkAsAvailable();
                break;
            case "occupied":
                table.MarkAsOccupied();
                break;
            case "cleaning":
                table.MarkAsCleaning();
                break;
            default:
                throw new ArgumentException($"Invalid status: {request.Status}");
        }

        _tableRepository.Update(table);
        await _tableRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation(
            "Changed table {TableId} status to {Status}",
            request.TableId, request.Status);

        return true;
    }
}
