using FluentValidation; using Microsoft.AspNetCore.Mvc; using Meezi.API.Models.Public; using Meezi.API.Services; using Meezi.Core.Authorization; using Meezi.Core.Enums; using Meezi.Core.Interfaces; using Meezi.Shared; namespace Meezi.API.Controllers; [Route("api/cafes/{cafeId}/reservations")] public class ReservationsController : CafeApiControllerBase { private readonly IReservationService _reservations; private readonly IValidator _createValidator; public ReservationsController( IReservationService reservations, IValidator createValidator) { _reservations = reservations; _createValidator = createValidator; } [HttpPost] public async Task Create( string cafeId, [FromBody] CreateReservationRequest request, ITenantContext tenant, CancellationToken ct) { if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied; if (EnsurePermission(tenant, Permission.CreateReservation) is { } permDenied) return permDenied; var validation = await _createValidator.ValidateAsync(request, ct); if (!validation.IsValid) return BadRequest(ValidationError(validation)); var data = await _reservations.CreateAsync(cafeId, request, ct); if (data is null) return BadRequest(new ApiResponse(false, null, new ApiError("INVALID_TABLE", "Table not found."))); return Ok(new ApiResponse(true, data)); } [HttpGet] public async Task List( string cafeId, ITenantContext tenant, [FromQuery] DateOnly? date, [FromQuery] ReservationStatus? status, CancellationToken ct) { if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied; var data = await _reservations.GetReservationsAsync(cafeId, date, status, ct); return Ok(new ApiResponse>(true, data)); } [HttpPatch("{id}/status")] public async Task UpdateStatus( string cafeId, string id, [FromBody] UpdateReservationStatusRequest request, ITenantContext tenant, CancellationToken ct) { if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied; if (EnsurePermission(tenant, Permission.EditReservation) is { } permDenied) return permDenied; var data = await _reservations.UpdateStatusAsync(cafeId, id, request.Status, ct); if (data is null) return NotFoundError(); return Ok(new ApiResponse(true, data)); } [HttpDelete("{id}")] public async Task Delete( string cafeId, string id, ITenantContext tenant, CancellationToken ct) { if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied; if (EnsurePermission(tenant, Permission.DeleteReservation) is { } permDenied) return permDenied; var deleted = await _reservations.DeleteAsync(cafeId, id, ct); if (!deleted) return NotFoundError(); return Ok(new ApiResponse(true, new { id })); } } public record UpdateReservationStatusRequest(ReservationStatus Status);