using AyCode.Core.Serializers.Binaries;
using AyCode.Core.Tests.TestModels;
using System.Runtime.CompilerServices;

namespace AyCode.Core.Benchmarks.Workloads.Scenarios;

/// <summary>
/// AcBinary benchmark, Byte[] I/O mode. The headline AcBinary row in every cell — compared
/// against <see cref="MemoryPackBenchmark{T}"/> as the SOTA baseline.
/// </summary>
public sealed class AcBinaryBenchmark<T> : ISerializerBenchmark where T : class
{
    private readonly T _order;
    private readonly AcBinarySerializerOptions _options;
    private readonly byte[] _serialized;

    public BenchmarkEngine Engine => BenchmarkEngine.AcBinary;
    public BenchmarkIoMode IoMode => BenchmarkIoMode.ByteArray;
    public BenchmarkDispatchMode DispatchMode => _options.UseGeneratedCode ? BenchmarkDispatchMode.SGen : BenchmarkDispatchMode.Runtime;
    public Type OrderType => typeof(T);
    public string OptionsPreset { get; }
    public int SerializedSize => _serialized.Length;
    public long SetupSerializeAllocBytes => 0;
    public long SetupDeserializeAllocBytes => 0;
    public string OptionsDescription => BenchmarkOptions.BuildAcBinary(_options);

    public AcBinaryBenchmark(T order, AcBinarySerializerOptions options, string optionsPreset)
    {
        _order = order;
        _options = options;
        OptionsPreset = optionsPreset;

        _serialized = AcBinarySerializer.Serialize(order, options);
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public void Serialize() => AcBinarySerializer.Serialize(_order, _options);

    [MethodImpl(MethodImplOptions.NoInlining)]
    public void Deserialize() => AcBinaryDeserializer.Deserialize<T>(_serialized, _options);

    public bool VerifyRoundTrip()
    {
        var bytes = AcBinarySerializer.Serialize(_order, _options);
        var roundTripped = AcBinaryDeserializer.Deserialize<T>(bytes, _options);

        return RoundTripValidator.DeepEqualsViaJson(_order, roundTripped);
    }
}
