// EN: Controller for reservation management.
// VI: Controller quản lý đặt bàn.

using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using FnbEngine.API.Application.Commands;
using FnbEngine.API.Application.Queries;
using FnbEngine.Domain.AggregatesModel.ReservationAggregate;

namespace FnbEngine.API.Controllers;

[ApiController]
[Route("api/v1/reservations")]
[Authorize]
public class ReservationsController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly IReservationRepository _reservationRepository;

    public ReservationsController(IMediator mediator, IReservationRepository reservationRepository)
    {
        _mediator = mediator;
        _reservationRepository = reservationRepository;
    }

    [HttpGet]
    [ProducesResponseType(typeof(ApiResponse<IEnumerable<ReservationDto>>), 200)]
    public async Task<ActionResult<ApiResponse<IEnumerable<ReservationDto>>>> GetReservations(
        [FromQuery] Guid shopId,
        [FromQuery] DateTime? date = null,
        CancellationToken ct = default)
    {
        var result = await _mediator.Send(new GetReservationsQuery(shopId, date), ct);
        return Ok(new ApiResponse<IEnumerable<ReservationDto>> { Success = true, Data = result });
    }

    [HttpPost]
    [ProducesResponseType(typeof(ApiResponse<CreateReservationResult>), 201)]
    [ProducesResponseType(400)]
    public async Task<ActionResult<ApiResponse<CreateReservationResult>>> CreateReservation(
        [FromBody] CreateReservationRequest request,
        CancellationToken ct = default)
    {
        var command = new CreateReservationCommand(
            request.ShopId, request.GuestName, request.PartySize, request.ReservationTime,
            request.Phone, request.TableId, request.Note);

        var result = await _mediator.Send(command, ct);
        return CreatedAtAction(nameof(GetReservations), new { shopId = request.ShopId },
            new ApiResponse<CreateReservationResult> { Success = true, Data = result });
    }

    [HttpPatch("{id}/status")]
    [ProducesResponseType(typeof(ApiResponse<bool>), 200)]
    [ProducesResponseType(404)]
    public async Task<ActionResult<ApiResponse<bool>>> UpdateStatus(
        Guid id,
        [FromBody] UpdateReservationStatusRequest request,
        CancellationToken ct = default)
    {
        var reservation = await _reservationRepository.GetByIdAsync(id, ct);
        if (reservation is null)
            return NotFound(new ApiResponse<bool> { Success = false, Error = "Reservation not found" });

        reservation.UpdateStatus(request.Status);
        _reservationRepository.Update(reservation);
        await _reservationRepository.UnitOfWork.SaveEntitiesAsync(ct);

        return Ok(new ApiResponse<bool> { Success = true, Data = true });
    }
}

public record CreateReservationRequest(
    Guid ShopId, string GuestName, int PartySize, DateTime ReservationTime,
    string? Phone = null, Guid? TableId = null, string? Note = null);

public record UpdateReservationStatusRequest(string Status);
