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 focused on different chunk sizes for parallel processing
/// </summary>
[MemoryDiagnoser]
[Config(typeof(InProcessConfig))]
public class ChunkSizeBenchmarks
{
    private string _sourceDirectory;
    private string _destinationDirectory;
    private ImageCreationService _imageCreationStuff;
    private PicSettings _picSettings;

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

    [Params(0, 5, 10, 20, 50)]
    public int ChunkSize { get; set; }

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

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

        Console.WriteLine($"Generating {ImageCount} test images for chunk size testing...");
        TestImageGenerator.GenerateTestImages(_sourceDirectory, ImageCount, width: 2000, height: 1500);

        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);
    }

    [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 ProcessWithVariableChunkSize()
    {
        var options = new ImageCreationService.Options
        {
            SourcePath = _sourceDirectory,
            DestinationPath = _destinationDirectory,
            MaxThreads = Environment.ProcessorCount,
            ChunksSize = ChunkSize,
            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);
    }
}
