using DocumentOperator.Application.Common.Interfaces;
using FluentValidation;
using MediatR;

namespace DocumentOperator.Application.MergePdfs;

/// <summary>
/// Command to merge multiple PDF documents into a single PDF.
/// </summary>
public record MergePdfsCommand : IRequest<byte[]>
{
    /// <summary>
    /// PDF streams to merge. Minimum 2 required. Each must be at Position=0.
    /// </summary>
    public required IReadOnlyList<Stream> PdfStreams { get; init; }

    /// <summary>
    /// Optional page ranges per PDF (null = all pages). 
    /// Format: "1-3,5" means pages 1, 2, 3, and 5.
    /// If provided, array length must match PdfStreams length.
    /// </summary>
    public IReadOnlyList<string?>? PageRanges { get; init; }
}

/// <summary>
/// Handler for MergePdfsCommand.
/// Delegates PDF merge operation to infrastructure layer.
/// </summary>
public class MergePdfsCommandHandler(IPdfProcessor pdfProcessor) 
    : IRequestHandler<MergePdfsCommand, byte[]>
{
    public async Task<byte[]> Handle(MergePdfsCommand request, CancellationToken cancellationToken)
    {
        return await pdfProcessor.MergePdfsAsync(request.PdfStreams, request.PageRanges);
    }
}

/// <summary>
/// Validator for MergePdfsCommand.
/// </summary>
public class MergePdfsCommandValidator : AbstractValidator<MergePdfsCommand>
{
    public MergePdfsCommandValidator()
    {
        RuleFor(x => x.PdfStreams)
            .NotNull()
            .WithMessage("PDF streams are required");

        RuleFor(x => x.PdfStreams)
            .Must(streams => streams != null && streams.Count >= 2)
            .WithMessage("At least 2 PDF files are required for merging");
    }
}
