using Extrudex.Domain.Enums;
using Extrudex.Domain.Interfaces;
using Microsoft.AspNetCore.Mvc;

namespace Extrudex.API.Controllers;

/// <summary>
/// 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.
/// </summary>
[ApiController]
[Route("api/qr")]
public class QrController : ControllerBase
{
    private readonly IQrCodeService _qrCodeService;
    private readonly ILogger<QrController> _logger;

    /// <summary>
    /// Initializes a new instance of the <see cref="QrController"/> class.
    /// </summary>
    /// <param name="qrCodeService">The QR code generation service.</param>
    /// <param name="logger">The logger for diagnostic output.</param>
    public QrController(IQrCodeService qrCodeService, ILogger<QrController> logger)
    {
        _qrCodeService = qrCodeService;
        _logger = logger;
    }

    /// <summary>
    /// 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 <c>format</c> query parameter is set to "svg".
    /// </summary>
    /// <param name="resourceType">
    /// The type of resource: <c>spool</c>, <c>printer</c>, or <c>location</c>.
    /// </param>
    /// <param name="id">The unique identifier of the resource.</param>
    /// <param name="format">
    /// Optional output format: <c>png</c> (default) or <c>svg</c>.
    /// SVG is resolution-independent and ideal for printing at any scale.
    /// </param>
    /// <param name="size">
    /// Optional pixel density per QR module for PNG output (default: 20).
    /// Ignored for SVG output. Range: 4–40.
    /// </param>
    /// <returns>The QR code image in the requested format.</returns>
    /// <response code="200">Returns the QR code image.</response>
    /// <response code="400">If the resource type is invalid or parameters are out of range.</response>
    [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<QrResourceType>(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");
    }
}