namespace ZB.MOM.NatsNet.Server;

public sealed partial class Account
{
    internal Exception? CheckNewConsumerConfig(ConsumerConfig current, ConsumerConfig next)
    {
        ArgumentNullException.ThrowIfNull(current);
        ArgumentNullException.ThrowIfNull(next);

        if (NatsConsumer.ConfigsEqualSansDelivery(current, next) &&
            string.Equals(current.DeliverSubject, next.DeliverSubject, StringComparison.Ordinal))
        {
            return null;
        }

        if (current.DeliverPolicy != next.DeliverPolicy)
            return new InvalidOperationException("deliver policy can not be updated");
        if (current.OptStartSeq != next.OptStartSeq)
            return new InvalidOperationException("start sequence can not be updated");
        if (current.OptStartTime != next.OptStartTime)
            return new InvalidOperationException("start time can not be updated");
        if (current.AckPolicy != next.AckPolicy)
            return new InvalidOperationException("ack policy can not be updated");
        if (current.ReplayPolicy != next.ReplayPolicy)
            return new InvalidOperationException("replay policy can not be updated");
        if (current.Heartbeat != next.Heartbeat)
            return new InvalidOperationException("heart beats can not be updated");
        if (current.FlowControl != next.FlowControl)
            return new InvalidOperationException("flow control can not be updated");

        if (!string.Equals(current.DeliverSubject, next.DeliverSubject, StringComparison.Ordinal))
        {
            if (string.IsNullOrWhiteSpace(current.DeliverSubject))
                return new InvalidOperationException("can not update pull consumer to push based");
            if (string.IsNullOrWhiteSpace(next.DeliverSubject))
                return new InvalidOperationException("can not update push consumer to pull based");
        }

        if (current.MaxWaiting != next.MaxWaiting)
            return new InvalidOperationException("max waiting can not be updated");

        if (next.BackOff is { Length: > 0 } && next.MaxDeliver != -1 && next.BackOff.Length > next.MaxDeliver)
            return new InvalidOperationException(JsApiErrors.NewJSConsumerMaxDeliverBackoffError().Description ?? "max deliver backoff invalid");

        return null;
    }
}
