using AutoMapper;
using DocumentOperator.Application.Common.DTOs;
using DocumentOperator.Application.Common.Interfaces;
using MediatR;

namespace DocumentOperator.Application.SwissQrCode.Queries;

/// <summary>
/// Query for extracting Swiss QR Code from PDF (supports both byte array and Base64 input)
/// </summary>
public record ExtractSwissQrCodeQuery : IRequest<SwissQrCodeExtractionResult>
{
    /// <summary>
    /// PDF as byte array (direct upload)
    /// </summary>
    public byte[]? PdfBytes { get; init; }

    /// <summary>
    /// PDF as Base64 string (API clients)
    /// </summary>
    public string? Base64Pdf { get; init; }

    /// <summary>
    /// Optional reference strings (passed through to response for external tracking)
    /// </summary>
    public IReadOnlyList<string>? References { get; init; }
}

/// <summary>
/// Handler for ExtractSwissQrCodeQuery
/// Orchestrates Swiss QR Code extraction using ISwissQrCodeProcessor and AutoMapper
/// </summary>
public class ExtractSwissQrCodeQueryHandler(ISwissQrCodeProcessor qrCodeProcessor, IMapper mapper) 
    : IRequestHandler<ExtractSwissQrCodeQuery, SwissQrCodeExtractionResult>
{
    /// <summary>
    /// Extracts and parses Swiss QR Code from the last page of the PDF
    /// </summary>
    public async Task<SwissQrCodeExtractionResult> Handle(ExtractSwissQrCodeQuery request, CancellationToken cancellationToken)
    {
        // Use byte[] if available, otherwise convert Base64
        byte[] pdfBytes = request.PdfBytes ?? Convert.FromBase64String(request.Base64Pdf!);

        // Extract and parse Swiss QR Code from last page (can throw PdfProcessingException or QrCodeNotFoundException)
        var qrCodeData = await qrCodeProcessor.ExtractSwissQrCodeAsync(pdfBytes, cancellationToken);

        // Map domain value object to DTO using AutoMapper
        var qrCodeDto = mapper.Map<SwissQrCodeDataDto>(qrCodeData);

        // Return references (passed through) + QR code data
        return new SwissQrCodeExtractionResult(
            References: request.References ?? [],
            QrCodeData: qrCodeDto
        );
    }
}
