namespace AyCode.Core.Benchmarks.Workloads.Scenarios;

/// <summary>
/// Serializer engine identifier — replaces the prior <c>Configuration.EngineXxx</c> string constants
/// with a type-safe enum. The benchmark-result <c>Engine</c> column uses <see cref="ToDisplay"/> for
/// the human-readable form.
/// </summary>
public enum BenchmarkEngine
{
    AcBinary,
    MemoryPack,
#if !AYCODE_NATIVEAOT
    MessagePack,
#endif
    SystemTextJson,
}

/// <summary>
/// I/O mode identifier — replaces the prior <c>Configuration.IoXxx</c> string constants. Note that
/// <see cref="NamedPipe"/> and <see cref="NamedPipeRaw"/> share the display string <c>"NamedPipe"</c>
/// (they distinguish chunked-framed vs raw-byte[] semantics, but render identically in the IO column);
/// the same applies to <see cref="InMemoryPipe"/> + <see cref="InMemoryRaw"/> (<c>"Pipe(in-mem)"</c>).
/// </summary>
public enum BenchmarkIoMode
{
    ByteArray,
    BufWrReuse,
    BufWrNew,
    String,
    NamedPipe,
    NamedPipeRaw,
    InMemoryPipe,
    InMemoryRaw,
}

/// <summary>
/// Dispatch mode identifier — replaces the prior <c>Configuration.ModeXxx</c> string constants.
/// Describes how property access / type dispatch happens for a given benchmark row:
/// <list type="bullet">
///   <item><see cref="SGen"/> — compile-time source generator path (Unsafe.As&lt;T&gt; direct fields, slot-array wrapper lookup).</item>
///   <item><see cref="Runtime"/> — reflection / compiled-delegate path.</item>
///   <item><see cref="Hybrid"/> — SGen root with non-SGen child types reached via bridge methods (see docs/BINARY/BINARY_SGEN.md).</item>
/// </list>
/// </summary>
public enum BenchmarkDispatchMode
{
    SGen,
    Runtime,
    Hybrid,
}

/// <summary>
/// Test-data layer filter — selects which test data cells participate in the run.
/// Replaces the prior string-typed <c>layer</c> parameter; CLI/menu callers parse user input via
/// <see cref="Enum.TryParse{T}(string, bool, out T)"/> with <c>ignoreCase: true</c>.
/// <list type="bullet">
///   <item><see cref="All"/> — no filter; every test data set runs.</item>
///   <item><see cref="Core"/>/<see cref="Comprehensive"/>/<see cref="Edge"/> — preset bundles (Comprehensive ⊇ Core, Edge ⊇ Comprehensive).</item>
///   <item><see cref="Small"/>/<see cref="Medium"/>/<see cref="Large"/>/<see cref="Repeated"/>/<see cref="Deep"/> — single-cell mini-suites for tight A/B iteration loops.</item>
/// </list>
/// </summary>
public enum BenchmarkLayer
{
    All,
    Core,
    Comprehensive,
    Edge,
    Small,
    Medium,
    Large,
    Repeated,
    Deep,
}

/// <summary>
/// Per-phase operation filter — selects which sides of the benchmark (Ser, Des, both) run for each
/// serializer. Round-trip-only benchmarks (NamedPipe etc.) treat <see cref="Deserialize"/> alone as
/// a no-op and only run on <see cref="Serialize"/> or <see cref="All"/>. Replaces the prior string-typed
/// <c>mode</c>/<c>opMode</c> parameter.
/// </summary>
public enum BenchmarkOpMode
{
    All,
    Serialize,
    Deserialize,
}

/// <summary>
/// Serializer-set selection — drives the runner's serializer-factory to return one of three
/// preset bundles instead of a magic string. Replaces the prior string-typed <c>serializerMode</c>
/// parameter.
/// <list type="bullet">
///   <item><see cref="Standard"/> — full suite minus AsyncPipe (the streaming benchmark is opt-in).</item>
///   <item><see cref="FastestByte"/> — focused AcBinary FastMode Byte[] vs MemoryPack Byte[] 1:1 comparison.</item>
///   <item><see cref="AsyncPipe"/> — streaming I/O isolation (NamedPipe + in-memory Pipe variants only).</item>
/// </list>
/// </summary>
public enum SerializerSelectionMode
{
    Standard,
    FastestByte,
    AsyncPipe,
}

/// <summary>
/// Display-string converters for the benchmark enums. Renders enum values into the column-friendly
/// human-readable form used by the per-row console table, the <c>.log</c> file CSV/formatted output,
/// and the <c>.LLM</c> markdown table. Centralised here so every output formatter renders identically.
/// </summary>
public static class BenchmarkEnumExtensions
{
    public static string ToDisplay(this BenchmarkEngine engine) => engine switch
    {
        BenchmarkEngine.AcBinary => "AcBinary",
        BenchmarkEngine.MemoryPack => "MemoryPack",
#if !AYCODE_NATIVEAOT
        BenchmarkEngine.MessagePack => "MessagePack",
#endif
        BenchmarkEngine.SystemTextJson => "System.Text.Json",
        _ => throw new ArgumentOutOfRangeException(nameof(engine), engine, null),
    };

    public static string ToDisplay(this BenchmarkIoMode mode) => mode switch
    {
        BenchmarkIoMode.ByteArray => "Byte[]",
        BenchmarkIoMode.BufWrReuse => "BufWr reuse",
        BenchmarkIoMode.BufWrNew => "BufWr new",
        BenchmarkIoMode.String => "String",
        BenchmarkIoMode.NamedPipe => "NamedPipe",
        BenchmarkIoMode.NamedPipeRaw => "NamedPipe",
        BenchmarkIoMode.InMemoryPipe => "Pipe(in-mem)",
        BenchmarkIoMode.InMemoryRaw => "Pipe(in-mem)",
        _ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null),
    };

    public static string ToDisplay(this BenchmarkDispatchMode mode) => mode switch
    {
        BenchmarkDispatchMode.SGen => "SGen",
        BenchmarkDispatchMode.Runtime => "Runtime",
        BenchmarkDispatchMode.Hybrid => "Hybrid",
        _ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null),
    };
}
