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 image processing with various configurations
/// </summary>
[MemoryDiagnoser]
[Config(typeof(InProcessConfig))]
public class ImageProcessingBenchmarks
{
    private string _sourceDirectory;
    private string _destinationDirectory;
    private ImageCreationService _imageCreationStuff;
    private PicSettings _picSettings;
    private ILogger<ImageCreationService> _logger;
    private ILogger<ImageCreatorGDI> _imageCreatorLogger;

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

    [Params(1, 2, 4, 8)]
    public int MaxThreads { get; set; }

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

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

        // Generate test images
        Console.WriteLine($"Generating {ImageCount} test images...");
        TestImageGenerator.GenerateTestImages(_sourceDirectory, ImageCount, width: 2000, height: 1500);

        // Setup logging
        var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder.SetMinimumLevel(LogLevel.Warning); // Reduce noise during benchmarks
        });

        _logger = loggerFactory.CreateLogger<ImageCreationService>();
        _imageCreatorLogger = loggerFactory.CreateLogger<ImageCreatorGDI>();

        // Setup PicSettings with default values
        _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()
    {
        // Clean up temp directories
        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()
    {
        // Clean destination directory before each iteration
        if (Directory.Exists(_destinationDirectory))
        {
            Directory.Delete(_destinationDirectory, recursive: true);
        }
        Directory.CreateDirectory(_destinationDirectory);
    }

    [Benchmark(Description = "Process images in parallel with chunking")]
    public async Task ProcessImagesParallelWithChunks()
    {
        var options = new ImageCreationService.Options
        {
            SourcePath = _sourceDirectory,
            DestinationPath = _destinationDirectory,
            MaxThreads = MaxThreads,
            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);
    }

    [Benchmark(Description = "Process images in parallel without chunking")]
    public async Task ProcessImagesParallelWithoutChunks()
    {
        var options = new ImageCreationService.Options
        {
            SourcePath = _sourceDirectory,
            DestinationPath = _destinationDirectory,
            MaxThreads = MaxThreads,
            ChunksSize = 0, // No chunking
            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);
    }

    [Benchmark(Description = "Process images linearly")]
    public async Task ProcessImagesLinear()
    {
        var options = new ImageCreationService.Options
        {
            SourcePath = _sourceDirectory,
            DestinationPath = _destinationDirectory,
            MaxThreads = MaxThreads,
            ChunksSize = 0,
            LinearExecution = true,
            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);
    }
}
