using Features.Breweries.Commands.CreateBrewery; using Features.Breweries.Commands.DeleteBrewery; using Features.Breweries.Commands.UpdateBrewery; using Features.Breweries.Dtos; using Features.Breweries.Queries.GetAllBreweries; using Features.Breweries.Queries.GetBreweryById; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Shared.Contracts; namespace Features.Breweries.Controllers; /// /// Provides CRUD endpoints for managing brewery posts. /// /// /// The controller is decorated with [Authorize(AuthenticationSchemes = "JWT")] by default; read endpoints /// ( and ) opt out via [AllowAnonymous]. /// /// Used to dispatch brewery commands and queries to their handlers. [ApiController] [Route("api/[controller]")] [Authorize(AuthenticationSchemes = "JWT")] public class BreweryController(IMediator mediator) : ControllerBase { /// /// Retrieves a single brewery post by its unique identifier. /// /// Allows anonymous access. /// The unique identifier of the brewery post to retrieve. /// /// A 200 OK result wrapping a of if found; /// otherwise a 404 Not Found result wrapping a error message. /// [AllowAnonymous] [HttpGet("{id:guid}")] public async Task>> GetById(Guid id) { var brewery = await mediator.Send(new GetBreweryByIdQuery(id)); if (brewery is null) return NotFound(new ResponseBody { Message = $"Brewery with ID {id} not found." }); return Ok(new ResponseBody { Message = "Brewery retrieved successfully.", Payload = brewery, }); } /// /// Retrieves a paginated list of brewery posts. /// /// Allows anonymous access. /// The maximum number of brewery posts to return, or null for no limit. /// The number of brewery posts to skip before returning results, or null for no offset. /// A 200 OK result wrapping a of a collection of . [AllowAnonymous] [HttpGet] public async Task>>> GetAll( [FromQuery] int? limit, [FromQuery] int? offset) { var breweries = await mediator.Send(new GetAllBreweriesQuery(limit, offset)); return Ok(new ResponseBody> { Message = "Breweries retrieved successfully.", Payload = breweries, }); } /// /// Creates a new brewery post. /// /// The brewery details to create, including the posting user, name, description, and location. /// A 201 Created result wrapping a of the newly created . [HttpPost] public async Task>> Create([FromBody] CreateBreweryCommand command) { var brewery = await mediator.Send(command); return Created($"/api/brewery/{brewery.BreweryPostId}", new ResponseBody { Message = "Brewery created successfully.", Payload = brewery, }); } /// /// Updates an existing brewery post. /// /// The unique identifier of the brewery post from the route, which must match 's ID. /// The updated brewery details, including the posting user, name, description, and optional location. /// /// A 200 OK result wrapping a of the updated if the /// update succeeds; otherwise a 400 Bad Request result wrapping a error message /// when the route ID does not match the payload ID. /// [HttpPut("{id:guid}")] public async Task>> Update(Guid id, [FromBody] UpdateBreweryCommand command) { if (command.BreweryPostId != id) return BadRequest(new ResponseBody { Message = "Route ID does not match payload ID." }); var brewery = await mediator.Send(command); return Ok(new ResponseBody { Message = "Brewery updated successfully.", Payload = brewery, }); } /// /// Deletes a brewery post. /// /// The unique identifier of the brewery post to delete. /// A 200 OK result wrapping a confirming the deletion. [HttpDelete("{id:guid}")] public async Task> Delete(Guid id) { await mediator.Send(new DeleteBreweryCommand(id)); return Ok(new ResponseBody { Message = "Brewery deleted successfully." }); } }