using Extrudex.Domain.Enums;
using Extrudex.Domain.Interfaces;
using Microsoft.AspNetCore.Mvc;
namespace Extrudex.API.Controllers;
///
/// Controller for generating QR codes for Extrudex resources (spools, printers, locations).
/// Returns QR codes as PNG or SVG images optimized for small label printing.
/// QR codes encode deep links that resolve to the resource's detail page.
///
[ApiController]
[Route("api/qr")]
public class QrController : ControllerBase
{
private readonly IQrCodeService _qrCodeService;
private readonly ILogger _logger;
///
/// Initializes a new instance of the class.
///
/// The QR code generation service.
/// The logger for diagnostic output.
public QrController(IQrCodeService qrCodeService, ILogger logger)
{
_qrCodeService = qrCodeService;
_logger = logger;
}
///
/// Generates a QR code for the specified resource type and ID.
/// Returns the QR code as a PNG image by default, or as SVG when
/// the format query parameter is set to "svg".
///
///
/// The type of resource: spool, printer, or location.
///
/// The unique identifier of the resource.
///
/// Optional output format: png (default) or svg.
/// SVG is resolution-independent and ideal for printing at any scale.
///
///
/// Optional pixel density per QR module for PNG output (default: 20).
/// Ignored for SVG output. Range: 4–40.
///
/// The QR code image in the requested format.
/// Returns the QR code image.
/// If the resource type is invalid or parameters are out of range.
[HttpGet("{resourceType}/{id:guid}")]
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK, "image/png")]
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK, "image/svg+xml")]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public IActionResult GetQrCode(
string resourceType,
Guid id,
[FromQuery] string format = "png",
[FromQuery] int size = 20)
{
_logger.LogDebug("Generating QR code: resourceType={ResourceType}, id={Id}, format={Format}, size={Size}",
resourceType, id, format, size);
// Parse resource type
if (!Enum.TryParse(resourceType, ignoreCase: true, out var parsedType))
{
return BadRequest(new
{
error = $"Invalid resource type: '{resourceType}'. " +
$"Valid values are: spool, printer, location."
});
}
// Validate format
format = format.ToLowerInvariant();
if (format is not ("png" or "svg"))
{
return BadRequest(new
{
error = $"Invalid format: '{format}'. Valid values are: png, svg."
});
}
// Validate size for PNG
if (format == "png" && (size < 4 || size > 40))
{
return BadRequest(new
{
error = $"Size must be between 4 and 40. Received: {size}."
});
}
if (format == "svg")
{
var svg = _qrCodeService.GenerateSvg(parsedType, id);
return Content(svg, "image/svg+xml");
}
var pngBytes = _qrCodeService.GeneratePng(parsedType, id, size);
return File(pngBytes, "image/png");
}
}