namespace NATS.Server.JetStream.Models;

public sealed class ConsumerConfig
{
    public string DurableName { get; set; } = string.Empty;
    public bool Ephemeral { get; set; }
    public string? FilterSubject { get; set; }
    public List<string> FilterSubjects { get; set; } = [];
    public AckPolicy AckPolicy { get; set; } = AckPolicy.None;
    public DeliverPolicy DeliverPolicy { get; set; } = DeliverPolicy.All;
    public ulong OptStartSeq { get; set; }
    public DateTime? OptStartTimeUtc { get; set; }
    public ReplayPolicy ReplayPolicy { get; set; } = ReplayPolicy.Instant;
    public int AckWaitMs { get; set; } = 30_000;
    public int MaxDeliver { get; set; } = 1;
    public int MaxAckPending { get; set; }
    public bool Push { get; set; }
    // Go: consumer.go:115 — deliver_subject routes push messages to a NATS subject
    public string DeliverSubject { get; set; } = string.Empty;
    public int HeartbeatMs { get; set; }
    public List<int> BackOffMs { get; set; } = [];
    public bool FlowControl { get; set; }
    public long RateLimitBps { get; set; }

    // Go: consumer.go — max_waiting limits the number of queued pull requests
    public int MaxWaiting { get; set; }

    // Go: consumer.go — max_request_batch limits batch size per pull request
    public int MaxRequestBatch { get; set; }

    // Go: consumer.go — max_request_max_bytes limits bytes per pull request
    public int MaxRequestMaxBytes { get; set; }

    // Go: consumer.go — max_request_expires limits expires duration per pull request (ms)
    public int MaxRequestExpiresMs { get; set; }

    // Go: ConsumerConfig.PauseUntil — pauses consumer delivery until this UTC time.
    // Null or zero time means not paused.
    // Added in v2.11, requires API level 1.
    // Go reference: server/consumer.go (PauseUntil field)
    public DateTime? PauseUntil { get; set; }

    // Go: ConsumerConfig.PriorityPolicy — consumer priority routing policy.
    // PriorityPinnedClient requires API level 1.
    // Go reference: server/consumer.go (PriorityPolicy field)
    public PriorityPolicy PriorityPolicy { get; set; } = PriorityPolicy.None;

    // Go: ConsumerConfig.PriorityGroups — list of priority group names.
    // Go reference: server/consumer.go (PriorityGroups field)
    public List<string> PriorityGroups { get; set; } = [];

    // Go: ConsumerConfig.PinnedTTL — TTL for pinned client assignment.
    // Go reference: server/consumer.go (PinnedTTL field)
    public long PinnedTtlMs { get; set; }

    // Go: ConsumerConfig.Metadata — user-supplied and server-managed key/value metadata.
    // Go reference: server/consumer.go (Metadata field)
    public Dictionary<string, string>? Metadata { get; set; }

    public string? ResolvePrimaryFilterSubject()
    {
        if (FilterSubjects.Count > 0)
            return FilterSubjects[0];

        return string.IsNullOrWhiteSpace(FilterSubject) ? null : FilterSubject;
    }
}

public enum AckPolicy
{
    None,
    Explicit,
    All,
}

/// <summary>
/// Consumer priority routing policy.
/// Go reference: server/consumer.go — PriorityNone, PriorityPinnedClient constants.
/// </summary>
public enum PriorityPolicy
{
    None = 0,
    Overflow = 1,
    PinnedClient = 2,
}
