using NAPS2.ImportExport;
using NAPS2.ImportExport.Images;
using NAPS2.Scan;
using NAPS2.Sdk.Tests.Asserts;
using Xunit;

namespace NAPS2.Sdk.Tests.ImportExport;

public class ImportPostProcessorTests : ContextualTests
{
    [Fact]
    public void NoPostProcessing()
    {
        using var image = ScanningContext.CreateProcessedImage(LoadImage(ImageResources.dog));
        using var image2 =
            ImportPostProcessor.AddPostProcessingData(image, null, null, new BarcodeDetectionOptions(), false);

        Assert.Null(image2.PostProcessingData.Thumbnail);
        Assert.Null(image2.PostProcessingData.ThumbnailTransformState);
        Assert.False(image2.PostProcessingData.Barcode.IsDetectionAttempted);
        Assert.False(IsDisposed(image2));
        image2.Dispose();
        Assert.False(IsDisposed(image));
    }

    [Fact]
    public void DisposesOriginalImageWithNoPostProcessing()
    {
        using var image = ScanningContext.CreateProcessedImage(LoadImage(ImageResources.dog));
        using var image2 =
            ImportPostProcessor.AddPostProcessingData(image, null, null, new BarcodeDetectionOptions(), true);

        Assert.False(IsDisposed(image2));
        image2.Dispose();
        Assert.True(IsDisposed(image));
    }

    [Fact]
    public void ThumbnailRendering()
    {
        using var image = ScanningContext.CreateProcessedImage(LoadImage(ImageResources.dog));
        using var image2 =
            ImportPostProcessor.AddPostProcessingData(image, null, 256, new BarcodeDetectionOptions(), false);

        var actual = image2.PostProcessingData.Thumbnail;

        Assert.NotNull(actual);
        Assert.NotNull(image2.PostProcessingData.ThumbnailTransformState);
        Assert.True(image2.PostProcessingData.ThumbnailTransformState.IsEmpty);
        ImageAsserts.Similar(ImageResources.dog_thumb_256, actual, ImageAsserts.XPLAT_RMSE_THRESHOLD,
            ignoreResolution: true);
    }

    [Fact]
    public void ThumbnailRenderingWithTransform()
    {
        using var image = ScanningContext.CreateProcessedImage(LoadImage(ImageResources.dog));
        using var image2 = image.WithTransform(new BrightnessTransform(300));
        using var image3 =
            ImportPostProcessor.AddPostProcessingData(image2, null, 256, new BarcodeDetectionOptions(), false);

        var actual = image3.PostProcessingData.Thumbnail;

        Assert.NotNull(actual);
        Assert.NotNull(image3.PostProcessingData.ThumbnailTransformState);
        Assert.Single(image3.PostProcessingData.ThumbnailTransformState.Transforms);
        var transform =
            Assert.IsType<BrightnessTransform>(image3.PostProcessingData.ThumbnailTransformState.Transforms[0]);
        Assert.Equal(300, transform.Brightness);
        ImageAsserts.Similar(ImageResources.dog_b_p300_thumb_256, actual, ImageAsserts.XPLAT_RMSE_THRESHOLD,
            ignoreResolution: true);
    }

    [Fact]
    public void ThumbnailRenderingWithPrerenderedImageAndDisposingOriginal()
    {
        using var rendered = LoadImage(ImageResources.dog);
        using var image = ScanningContext.CreateProcessedImage(rendered);
        using var image2 =
            ImportPostProcessor.AddPostProcessingData(image, rendered, 256, new BarcodeDetectionOptions(), true);

        var actual = image2.PostProcessingData.Thumbnail;

        Assert.NotNull(actual);
        Assert.NotNull(image2.PostProcessingData.ThumbnailTransformState);
        Assert.True(image2.PostProcessingData.ThumbnailTransformState.IsEmpty);
        ImageAsserts.Similar(ImageResources.dog_thumb_256, actual, ImageAsserts.XPLAT_RMSE_THRESHOLD,
            ignoreResolution: true);
        Assert.False(IsDisposed(rendered));
        Assert.False(IsDisposed(image2));
        image2.Dispose();
        Assert.True(IsDisposed(image));
    }

    [Fact]
    public void BarcodeDetection()
    {
        using var image = ScanningContext.CreateProcessedImage(LoadImage(ImageResources.patcht));
        var barcodeOptions = new BarcodeDetectionOptions { DetectBarcodes = true };
        using var image2 = ImportPostProcessor.AddPostProcessingData(image, null, null, barcodeOptions, false);

        Assert.True(image2.PostProcessingData.Barcode.IsPatchT);
    }

    [Fact]
    public void BarcodeDetectionWithPrerenderedImage()
    {
        using var rendered = LoadImage(ImageResources.patcht);
        using var image = ScanningContext.CreateProcessedImage(rendered);
        var barcodeOptions = new BarcodeDetectionOptions { DetectBarcodes = true };
        using var image2 = ImportPostProcessor.AddPostProcessingData(image, rendered, null, barcodeOptions, false);

        Assert.True(image2.PostProcessingData.Barcode.IsPatchT);
    }
}