using System;
using System.Collections.Concurrent;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Engines;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Toolchains.InProcess.Emit;
using MaddoShared.Benchmarks.Helpers;
using Microsoft.Extensions.Logging;

namespace MaddoShared.Benchmarks;

/// <summary>
/// Benchmarks for comparing performance with different image sizes
/// </summary>
[MemoryDiagnoser]
[Config(typeof(InProcessConfig))]
public class ImageSizeBenchmarks
{
    private string _sourceDirectory;
    private string _destinationDirectory;
    private ImageCreationService _imageCreationStuff;
    private PicSettings _picSettings;

    [Params(50)]
    public int ImageCount { get; set; }

    public enum ImageSize
    {
        Small,   // 1280x960
        Medium,  // 2560x1920
        Large,   // 4000x3000
        ExtraLarge // 6000x4000
    }

    [ParamsAllValues]
    public ImageSize Size { get; set; }

    [GlobalSetup]
    public void Setup()
    {
        var tempBase = Path.Combine(Path.GetTempPath(), "SizeBenchmarks", Guid.NewGuid().ToString());
        _sourceDirectory = Path.Combine(tempBase, "Source");
        _destinationDirectory = Path.Combine(tempBase, "Destination");

        Directory.CreateDirectory(_sourceDirectory);
        Directory.CreateDirectory(_destinationDirectory);

        var (width, height) = GetDimensions(Size);
        Console.WriteLine($"Generating {ImageCount} test images at {width}x{height}...");
        TestImageGenerator.GenerateTestImages(_sourceDirectory, ImageCount, width, height);

        var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder.SetMinimumLevel(LogLevel.Warning);
        });

        var logger = loggerFactory.CreateLogger<ImageCreationService>();
        var imageCreatorLogger = loggerFactory.CreateLogger<ImageCreatorGDI>();

        _picSettings = new PicSettings
        {
            DirectorySorgente = _sourceDirectory,
            DirectoryDestinazione = _destinationDirectory,
            DimStandard = 800,
            DimStandardMiniatura = 200,
            LarghezzaBig = 1024,
            AltezzaBig = 768,
            LarghezzaSmall = 200,
            AltezzaSmall = 150,
            CreaMiniature = true,
            AggiungiScritteMiniature = false,
            UsaForzaJpg = true,
            UsaRotazioneAutomatica = true,
            LogoAggiungi = false,
            FotoGrandeDimOrigina = false,
            TestoNome = false,
            NomeData = false,
            Suffisso = "_small",
            Margine = 10,
            Trasparenza = 100
        };

        var imageCreatorService = new ImageCreatorGDI(_picSettings, imageCreatorLogger);
        _imageCreationStuff = new ImageCreationService(logger, _picSettings, imageCreatorService);
    }

    private static (int width, int height) GetDimensions(ImageSize size)
    {
        return size switch
        {
            ImageSize.Small => (1280, 960),
            ImageSize.Medium => (2560, 1920),
            ImageSize.Large => (4000, 3000),
            ImageSize.ExtraLarge => (6000, 4000),
            _ => throw new ArgumentException($"Unknown size: {size}")
        };
    }

    [GlobalCleanup]
    public void Cleanup()
    {
        try
        {
            var tempBase = Path.GetDirectoryName(_sourceDirectory);
            if (Directory.Exists(tempBase))
            {
                Directory.Delete(tempBase, recursive: true);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Cleanup error: {ex.Message}");
        }
    }

    [IterationSetup]
    public void IterationSetup()
    {
        if (Directory.Exists(_destinationDirectory))
        {
            Directory.Delete(_destinationDirectory, recursive: true);
        }
        Directory.CreateDirectory(_destinationDirectory);
    }

    [Benchmark]
    public async Task ProcessDifferentImageSizes()
    {
        var options = new ImageCreationService.Options
        {
            SourcePath = _sourceDirectory,
            DestinationPath = _destinationDirectory,
            MaxThreads = Environment.ProcessorCount,
            ChunksSize = 10,
            LinearExecution = false,
            AggiornaSottodirectory = false,
            CreaSottocartelle = false,
            FilePerCartella = 100,
            SuffissoCartelle = "",
            CifreContatore = 4,
            NumerazioneType = NumerazioneType.Progressiva
        };

        var results = new ConcurrentBag<string>();
        await _imageCreationStuff.ProcessImagesParallel(options, results, null, CancellationToken.None);
    }
}
