using Grpc.Core;

namespace ZB.MOM.WW.MxGateway.Tests.TestSupport;

/// <summary>
/// Minimal in-memory <see cref="ServerCallContext"/> for exercising gRPC service
/// implementations directly in unit tests, without a real gRPC transport.
/// </summary>
public sealed class TestServerCallContext : ServerCallContext
{
    private const string DefaultPeer = "ipv4:127.0.0.1:5000";

    private readonly Metadata _requestHeaders;
    private readonly Metadata _responseTrailers = [];
    private readonly Dictionary<object, object> _userState = [];
    private readonly CancellationToken _cancellationToken;
    private readonly string _peer;
    private Status _status;
    private WriteOptions? _writeOptions;

    /// <summary>Initializes the context with the supplied request headers and cancellation token.</summary>
    /// <param name="requestHeaders">Request headers visible to the service; defaults to empty.</param>
    /// <param name="cancellationToken">Cancellation token surfaced to the service.</param>
    /// <param name="peer">
    /// Transport peer address surfaced as <see cref="ServerCallContext.Peer"/>; defaults to a
    /// loopback address. Tests that exercise per-peer partitioning (for example the API-key failure
    /// limiter) pass distinct values to model separate network sources.
    /// </param>
    public TestServerCallContext(
        Metadata? requestHeaders = null,
        CancellationToken cancellationToken = default,
        string? peer = null)
    {
        _requestHeaders = requestHeaders ?? [];
        _cancellationToken = cancellationToken;
        _peer = peer ?? DefaultPeer;
    }

    /// <inheritdoc />
    protected override string MethodCore => "/mxaccess_gateway.v1.MxAccessGateway/Test";

    /// <inheritdoc />
    protected override string HostCore => "localhost";

    /// <inheritdoc />
    protected override string PeerCore => _peer;

    /// <inheritdoc />
    protected override DateTime DeadlineCore => DateTime.UtcNow.AddMinutes(1);

    /// <inheritdoc />
    protected override Metadata RequestHeadersCore => _requestHeaders;

    /// <inheritdoc />
    protected override CancellationToken CancellationTokenCore => _cancellationToken;

    /// <inheritdoc />
    protected override Metadata ResponseTrailersCore => _responseTrailers;

    /// <inheritdoc />
    protected override Status StatusCore
    {
        get => _status;
        set => _status = value;
    }

    /// <inheritdoc />
    protected override WriteOptions? WriteOptionsCore
    {
        get => _writeOptions;
        set => _writeOptions = value;
    }

    /// <inheritdoc />
    protected override AuthContext AuthContextCore { get; } = new(
        string.Empty,
        new Dictionary<string, List<AuthProperty>>(StringComparer.Ordinal));

    /// <inheritdoc />
    protected override IDictionary<object, object> UserStateCore => _userState;

    /// <inheritdoc />
    protected override Task WriteResponseHeadersAsyncCore(Metadata responseHeaders) => Task.CompletedTask;

    /// <inheritdoc />
    protected override ContextPropagationToken CreatePropagationTokenCore(ContextPropagationOptions? options) =>
        throw new NotSupportedException();
}
