using DocumentService.Application.Common.DTOs;
using DocumentService.Application.SignPdf;
using DocumentService.Domain.Common.Exceptions;
using MediatR;
using Microsoft.AspNetCore.Mvc;
namespace DocumentService.API.Controllers;
///
/// Controller for PDF digital signing (PKCS#11 / company certificate).
///
[ApiController]
[Route("api/pdf/signature")]
public class PdfSignatureController(IMediator mediator) : ControllerBase
{
///
/// Digitally signs a PDF using the configured PKCS#11 signing infrastructure.
///
/// Base64-encoded PDF, optional signature image, and signing options
/// Cancellation token
/// Signed PDF
/// PDF signed successfully - returns signed PDF
/// Invalid input (Base64 format error, invalid appearance)
/// Internal server error during signing
[HttpPost("sign")]
[Consumes("application/json")]
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)]
public async Task Sign([FromBody] SignPdfRequest request, CancellationToken cancellationToken)
{
byte[] signedPdf;
try
{
signedPdf = await mediator.Send(new SignPdfCommand
{
InputPdf = new MemoryStream(Convert.FromBase64String(request.Base64Pdf)),
Options = request.Options,
SignatureImage = string.IsNullOrWhiteSpace(request.Base64SignatureImage)
? null
: new MemoryStream(Convert.FromBase64String(request.Base64SignatureImage))
}, cancellationToken);
}
catch (FormatException ex)
{
throw new BadRequestException("Invalid Base64 format: " + ex.Message);
}
return File(signedPdf, "application/pdf", "signed.pdf");
}
}
///
/// Request DTO for PDF signing via JSON payload.
///
public sealed class SignPdfRequest
{
///
/// Base64-encoded PDF to sign.
///
public required string Base64Pdf { get; init; }
///
/// Optional Base64-encoded signature image (PNG/JPEG).
///
public string? Base64SignatureImage { get; init; }
///
/// Signing options (metadata + appearance).
///
public required PdfSignOptionsDto Options { get; init; }
}