using System.Diagnostics;
using System.Text;
using Microsoft.Extensions.Logging;
using Serilog.Context;

namespace ZB.MOM.WW.CBDD.Tests.Benchmark;

public class ManualBenchmark
{
    private static readonly StringBuilder _log = new();

    private static void Log(ILogger logger, string message = "")
    {
        logger.LogInformation("{Message}", message);
        _log.AppendLine(message);
    }

    /// <summary>
    ///     Tests run.
    /// </summary>
    /// <param name="logger">Logger for benchmark progress and results.</param>
    public static void Run(ILogger logger)
    {
        using var _ = LogContext.PushProperty("Benchmark", nameof(ManualBenchmark));
        _log.Clear();
        Log(logger, "=== MANUAL BENCHMARK: CBDD ===");
        Log(logger, $"Date: {DateTime.Now}");
        Log(logger, "Testing: Complex Objects (Nested Documents + Collections)\n");

        long batchInsertMs;
        long singleInsertMs;
        long readByIdMs;

        using (LogContext.PushProperty("Phase", "BatchInsert"))
        {
            Log(logger, "1. Batch Insert (1000 items)");
            var insertBench = new InsertBenchmarks();
            insertBench.Setup();
            insertBench.IterationSetup();
            try
            {
                var sw = Stopwatch.StartNew();
                insertBench.DocumentDb_Insert_Batch();
                sw.Stop();
                batchInsertMs = sw.ElapsedMilliseconds;
                Log(logger, $"  CBDD InsertBulk (1000): {batchInsertMs} ms");
            }
            finally
            {
                insertBench.Cleanup();
            }
        }

        using (LogContext.PushProperty("Phase", "FindById"))
        {
            Log(logger, "\n2. FindById Performance (1000 operations)");
            var readBench = new ReadBenchmarks();
            readBench.Setup();
            try
            {
                var sw = Stopwatch.StartNew();
                for (var i = 0; i < 1000; i++) readBench.DocumentDb_FindById();
                sw.Stop();
                readByIdMs = sw.ElapsedMilliseconds;
                Log(logger, $"  CBDD FindById x1000: {readByIdMs} ms ({(double)readByIdMs / 1000:F3} ms/op)");
            }
            finally
            {
                readBench.Cleanup();
            }
        }

        using (LogContext.PushProperty("Phase", "SingleInsert"))
        {
            Log(logger, "\n3. Single Insert");
            var insertBench = new InsertBenchmarks();
            insertBench.Setup();
            insertBench.IterationSetup();
            try
            {
                var sw = Stopwatch.StartNew();
                insertBench.DocumentDb_Insert_Single();
                sw.Stop();
                singleInsertMs = sw.ElapsedMilliseconds;
                Log(logger, $"  CBDD Single Insert: {singleInsertMs} ms");
            }
            finally
            {
                insertBench.Cleanup();
            }
        }

        Log(logger, "\n============================================================================");
        Log(logger, "BENCHMARK RESULTS (CBDD ONLY):");
        Log(logger, "============================================================================");
        Log(logger, $"Batch Insert (1000): {batchInsertMs} ms");
        Log(logger, $"FindById x1000:      {readByIdMs} ms");
        Log(logger, $"Single Insert:       {singleInsertMs} ms");

        string artifactsDir = Path.Combine(AppContext.BaseDirectory, "BenchmarkDotNet.Artifacts", "results");
        if (!Directory.Exists(artifactsDir)) Directory.CreateDirectory(artifactsDir);

        string filePath = Path.Combine(artifactsDir, "manual_report.txt");
        File.WriteAllText(filePath, _log.ToString());
        logger.LogInformation("Report saved to: {FilePath}", filePath);
    }
}