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." });
}
}