using DocumentOperator.Application.Common.Interfaces;
using DocumentOperator.Application.Features.Documents.ValidatePdf;
using DocumentOperator.Domain.Common.Exceptions;
using DocumentOperator.Domain.Models.ValueObjects;
using FluentAssertions;
using Moq;
using Xunit;

namespace DocumentOperator.Tests.Unit.Application.Features.ValidatePdf;

public class ValidatePdfHandlerTests
{
    private readonly Mock<IPdfProcessor> _mockPdfProcessor;
    private readonly ValidatePdfHandler _handler;

    public ValidatePdfHandlerTests()
    {
        _mockPdfProcessor = new Mock<IPdfProcessor>();
        _handler = new ValidatePdfHandler(_mockPdfProcessor.Object);
    }

    [Fact]
    public async Task Handle_ValidPdf_ReturnsPdfMetadata()
    {
        // Arrange
        var base64Pdf = Convert.ToBase64String(new byte[] { 0x25, 0x50, 0x44, 0x46 }); // "%PDF"
        var pdfContent = Base64String.Create(base64Pdf);
        var query = new ValidatePdfQuery(pdfContent);

        var expectedMetadata = new PdfMetadata(
            pageCount: 5,
            fileSizeBytes: 1024,
            pdfVersion: "1.4",
            hasAttachments: false,
            attachmentCount: 0
        );

        _mockPdfProcessor
            .Setup(x => x.ValidateAsync(It.IsAny<byte[]>()))
            .ReturnsAsync(expectedMetadata);

        // Act
        var result = await _handler.Handle(query, CancellationToken.None);

        // Assert
        result.Should().NotBeNull();
        result.PageCount.Should().Be(5);
        result.FileSizeBytes.Should().Be(1024);
        result.PdfVersion.Should().Be("1.4");
        result.HasAttachments.Should().BeFalse();
        result.AttachmentCount.Should().Be(0);

        _mockPdfProcessor.Verify(
            x => x.ValidateAsync(It.IsAny<byte[]>()),
            Times.Once
        );
    }

    [Fact]
    public async Task Handle_PdfProcessorThrowsException_PropagatesException()
    {
        // Arrange
        var base64Pdf = Convert.ToBase64String(new byte[] { 0x25, 0x50, 0x44, 0x46 });
        var pdfContent = Base64String.Create(base64Pdf);
        var query = new ValidatePdfQuery(pdfContent);

        _mockPdfProcessor
            .Setup(x => x.ValidateAsync(It.IsAny<byte[]>()))
            .ThrowsAsync(new PdfProcessingException("Invalid PDF format"));

        // Act
        Func<Task> act = async () => await _handler.Handle(query, CancellationToken.None);

        // Assert
        await act.Should().ThrowAsync<PdfProcessingException>()
            .WithMessage("Invalid PDF format");
    }
}
