#!/usr/bin/env bash
set -euo pipefail

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
output_file="$repo_root/dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamErrors.GeneratedConstructors.cs"

simple_methods=(
  "NewJSAccountResourcesExceededError|AccountResourcesExceeded"
  "NewJSAtomicPublishContainsDuplicateMessageError|AtomicPublishContainsDuplicateMessage"
  "NewJSAtomicPublishDisabledError|AtomicPublishDisabled"
  "NewJSAtomicPublishIncompleteBatchError|AtomicPublishIncompleteBatch"
  "NewJSAtomicPublishInvalidBatchCommitError|AtomicPublishInvalidBatchCommit"
  "NewJSAtomicPublishInvalidBatchIDError|AtomicPublishInvalidBatchID"
  "NewJSAtomicPublishMissingSeqError|AtomicPublishMissingSeq"
  "NewJSBadRequestError|BadRequest"
  "NewJSClusterIncompleteError|ClusterIncomplete"
  "NewJSClusterNotActiveError|ClusterNotActive"
  "NewJSClusterNotAssignedError|ClusterNotAssigned"
  "NewJSClusterNotAvailError|ClusterNotAvail"
  "NewJSClusterNotLeaderError|ClusterNotLeader"
  "NewJSClusterPeerNotMemberError|ClusterPeerNotMember"
  "NewJSClusterRequiredError|ClusterRequired"
  "NewJSClusterServerMemberChangeInflightError|ClusterServerMemberChangeInflight"
  "NewJSClusterServerNotMemberError|ClusterServerNotMember"
  "NewJSClusterTagsError|ClusterTags"
  "NewJSClusterUnSupportFeatureError|ClusterUnSupportFeature"
  "NewJSConsumerAckPolicyInvalidError|ConsumerAckPolicyInvalid"
  "NewJSConsumerAckWaitNegativeError|ConsumerAckWaitNegative"
  "NewJSConsumerAlreadyExistsError|ConsumerAlreadyExists"
  "NewJSConsumerBackOffNegativeError|ConsumerBackOffNegative"
  "NewJSConsumerBadDurableNameError|ConsumerBadDurableName"
  "NewJSConsumerConfigRequiredError|ConsumerConfigRequired"
  "NewJSConsumerCreateDurableAndNameMismatchError|ConsumerCreateDurableAndNameMismatch"
  "NewJSConsumerCreateFilterSubjectMismatchError|ConsumerCreateFilterSubjectMismatch"
  "NewJSConsumerDeliverCycleError|ConsumerDeliverCycle"
  "NewJSConsumerDeliverToWildcardsError|ConsumerDeliverToWildcards"
  "NewJSConsumerDirectRequiresEphemeralError|ConsumerDirectRequiresEphemeral"
  "NewJSConsumerDirectRequiresPushError|ConsumerDirectRequiresPush"
  "NewJSConsumerDoesNotExistError|ConsumerDoesNotExist"
  "NewJSConsumerDuplicateFilterSubjectsError|ConsumerDuplicateFilterSubjects"
  "NewJSConsumerDurableNameNotInSubjectError|ConsumerDurableNameNotInSubject"
  "NewJSConsumerDurableNameNotMatchSubjectError|ConsumerDurableNameNotMatchSubject"
  "NewJSConsumerDurableNameNotSetError|ConsumerDurableNameNotSet"
  "NewJSConsumerEmptyFilterError|ConsumerEmptyFilter"
  "NewJSConsumerEmptyGroupNameError|ConsumerEmptyGroupName"
  "NewJSConsumerEphemeralWithDurableInSubjectError|ConsumerEphemeralWithDurableInSubject"
  "NewJSConsumerEphemeralWithDurableNameError|ConsumerEphemeralWithDurableName"
  "NewJSConsumerExistingActiveError|ConsumerExistingActive"
  "NewJSConsumerFCRequiresPushError|ConsumerFCRequiresPush"
  "NewJSConsumerFilterNotSubsetError|ConsumerFilterNotSubset"
  "NewJSConsumerHBRequiresPushError|ConsumerHBRequiresPush"
  "NewJSConsumerInvalidDeliverSubjectError|ConsumerInvalidDeliverSubject"
  "NewJSConsumerInvalidGroupNameError|ConsumerInvalidGroupName"
  "NewJSConsumerInvalidPriorityGroupError|ConsumerInvalidPriorityGroup"
  "NewJSConsumerMaxDeliverBackoffError|ConsumerMaxDeliverBackoff"
  "NewJSConsumerMaxPendingAckPolicyRequiredError|ConsumerMaxPendingAckPolicyRequired"
  "NewJSConsumerMaxRequestBatchNegativeError|ConsumerMaxRequestBatchNegative"
  "NewJSConsumerMaxRequestExpiresTooSmallError|ConsumerMaxRequestExpiresTooSmall"
  "NewJSConsumerMaxWaitingNegativeError|ConsumerMaxWaitingNegative"
  "NewJSConsumerMultipleFiltersNotAllowedError|ConsumerMultipleFiltersNotAllowed"
  "NewJSConsumerNameContainsPathSeparatorsError|ConsumerNameContainsPathSeparators"
  "NewJSConsumerNameExistError|ConsumerNameExist"
  "NewJSConsumerNotFoundError|ConsumerNotFound"
  "NewJSConsumerOfflineError|ConsumerOffline"
  "NewJSConsumerOnMappedError|ConsumerOnMapped"
  "NewJSConsumerOverlappingSubjectFiltersError|ConsumerOverlappingSubjectFilters"
  "NewJSConsumerPinnedTTLWithoutPriorityPolicyNoneError|ConsumerPinnedTTLWithoutPriorityPolicyNone"
  "NewJSConsumerPriorityGroupWithPolicyNoneError|ConsumerPriorityGroupWithPolicyNone"
  "NewJSConsumerPriorityPolicyWithoutGroupError|ConsumerPriorityPolicyWithoutGroup"
  "NewJSConsumerPullNotDurableError|ConsumerPullNotDurable"
  "NewJSConsumerPullRequiresAckError|ConsumerPullRequiresAck"
  "NewJSConsumerPullWithRateLimitError|ConsumerPullWithRateLimit"
  "NewJSConsumerPushMaxWaitingError|ConsumerPushMaxWaiting"
  "NewJSConsumerPushWithPriorityGroupError|ConsumerPushWithPriorityGroup"
  "NewJSConsumerReplacementWithDifferentNameError|ConsumerReplacementWithDifferentName"
  "NewJSConsumerReplayPolicyInvalidError|ConsumerReplayPolicyInvalid"
  "NewJSConsumerReplicasExceedsStreamError|ConsumerReplicasExceedsStream"
  "NewJSConsumerReplicasShouldMatchStreamError|ConsumerReplicasShouldMatchStream"
  "NewJSConsumerSmallHeartbeatError|ConsumerSmallHeartbeat"
  "NewJSConsumerWQConsumerNotDeliverAllError|ConsumerWQConsumerNotDeliverAll"
  "NewJSConsumerWQConsumerNotUniqueError|ConsumerWQConsumerNotUnique"
  "NewJSConsumerWQMultipleUnfilteredError|ConsumerWQMultipleUnfiltered"
  "NewJSConsumerWQRequiresExplicitAckError|ConsumerWQRequiresExplicitAck"
  "NewJSConsumerWithFlowControlNeedsHeartbeatsError|ConsumerWithFlowControlNeedsHeartbeats"
  "NewJSInsufficientResourcesError|InsufficientResources"
  "NewJSMaximumConsumersLimitError|MaximumConsumersLimit"
  "NewJSMaximumStreamsLimitError|MaximumStreamsLimit"
  "NewJSMemoryResourcesExceededError|MemoryResourcesExceeded"
  "NewJSMessageCounterBrokenError|MessageCounterBroken"
  "NewJSMessageIncrDisabledError|MessageIncrDisabled"
  "NewJSMessageIncrInvalidError|MessageIncrInvalid"
  "NewJSMessageIncrMissingError|MessageIncrMissing"
  "NewJSMessageIncrPayloadError|MessageIncrPayload"
  "NewJSMessageSchedulesDisabledError|MessageSchedulesDisabled"
  "NewJSMessageSchedulesPatternInvalidError|MessageSchedulesPatternInvalid"
  "NewJSMessageSchedulesRollupInvalidError|MessageSchedulesRollupInvalid"
  "NewJSMessageSchedulesSourceInvalidError|MessageSchedulesSourceInvalid"
  "NewJSMessageSchedulesTTLInvalidError|MessageSchedulesTTLInvalid"
  "NewJSMessageSchedulesTargetInvalidError|MessageSchedulesTargetInvalid"
  "NewJSMessageTTLDisabledError|MessageTTLDisabled"
  "NewJSMessageTTLInvalidError|MessageTTLInvalid"
  "NewJSMirrorInvalidStreamNameError|MirrorInvalidStreamName"
  "NewJSMirrorMaxMessageSizeTooBigError|MirrorMaxMessageSizeTooBig"
  "NewJSMirrorMultipleFiltersNotAllowedError|MirrorMultipleFiltersNotAllowed"
  "NewJSMirrorOverlappingSubjectFiltersError|MirrorOverlappingSubjectFilters"
  "NewJSMirrorWithAtomicPublishError|MirrorWithAtomicPublish"
  "NewJSMirrorWithCountersError|MirrorWithCounters"
  "NewJSMirrorWithFirstSeqError|MirrorWithFirstSeq"
  "NewJSMirrorWithMsgSchedulesError|MirrorWithMsgSchedules"
  "NewJSMirrorWithSourcesError|MirrorWithSources"
  "NewJSMirrorWithStartSeqAndTimeError|MirrorWithStartSeqAndTime"
  "NewJSMirrorWithSubjectFiltersError|MirrorWithSubjectFilters"
  "NewJSMirrorWithSubjectsError|MirrorWithSubjects"
  "NewJSNoAccountError|NoAccount"
  "NewJSNoLimitsError|NoLimits"
  "NewJSNoMessageFoundError|NoMessageFound"
  "NewJSNotEmptyRequestError|NotEmptyRequest"
  "NewJSNotEnabledError|NotEnabled"
  "NewJSNotEnabledForAccountError|NotEnabledForAccount"
  "NewJSReplicasCountCannotBeNegativeError|ReplicasCountCannotBeNegative"
  "NewJSRequiredApiLevelError|RequiredApiLevel"
  "NewJSSnapshotDeliverSubjectInvalidError|SnapshotDeliverSubjectInvalid"
  "NewJSSourceDuplicateDetectedError|SourceDuplicateDetected"
  "NewJSSourceInvalidStreamNameError|SourceInvalidStreamName"
  "NewJSSourceMaxMessageSizeTooBigError|SourceMaxMessageSizeTooBig"
  "NewJSSourceMultipleFiltersNotAllowedError|SourceMultipleFiltersNotAllowed"
  "NewJSSourceOverlappingSubjectFiltersError|SourceOverlappingSubjectFilters"
  "NewJSSourceWithMsgSchedulesError|SourceWithMsgSchedules"
  "NewJSStorageResourcesExceededError|StorageResourcesExceeded"
  "NewJSStreamDuplicateMessageConflictError|StreamDuplicateMessageConflict"
  "NewJSStreamExpectedLastSeqPerSubjectInvalidError|StreamExpectedLastSeqPerSubjectInvalid"
  "NewJSStreamExpectedLastSeqPerSubjectNotReadyError|StreamExpectedLastSeqPerSubjectNotReady"
  "NewJSStreamHeaderExceedsMaximumError|StreamHeaderExceedsMaximum"
  "NewJSStreamInfoMaxSubjectsError|StreamInfoMaxSubjects"
  "NewJSStreamInvalidError|StreamInvalid"
  "NewJSStreamMaxBytesRequiredError|StreamMaxBytesRequired"
  "NewJSStreamMaxStreamBytesExceededError|StreamMaxStreamBytesExceeded"
  "NewJSStreamMessageExceedsMaximumError|StreamMessageExceedsMaximum"
  "NewJSStreamMinLastSeqError|StreamMinLastSeq"
  "NewJSStreamMirrorNotUpdatableError|StreamMirrorNotUpdatable"
  "NewJSStreamMismatchError|StreamMismatch"
  "NewJSStreamMoveAndScaleError|StreamMoveAndScale"
  "NewJSStreamMoveNotInProgressError|StreamMoveNotInProgress"
  "NewJSStreamNameContainsPathSeparatorsError|StreamNameContainsPathSeparators"
  "NewJSStreamNameExistError|StreamNameExist"
  "NewJSStreamNameExistRestoreFailedError|StreamNameExistRestoreFailed"
  "NewJSStreamNotFoundError|StreamNotFound"
  "NewJSStreamNotMatchError|StreamNotMatch"
  "NewJSStreamOfflineError|StreamOffline"
  "NewJSStreamReplicasNotSupportedError|StreamReplicasNotSupported"
  "NewJSStreamReplicasNotUpdatableError|StreamReplicasNotUpdatable"
  "NewJSStreamSealedError|StreamSealed"
  "NewJSStreamSequenceNotMatchError|StreamSequenceNotMatch"
  "NewJSStreamSubjectOverlapError|StreamSubjectOverlap"
  "NewJSStreamTemplateNotFoundError|StreamTemplateNotFound"
  "NewJSStreamTooManyRequestsError|StreamTooManyRequests"
  "NewJSStreamWrongLastSequenceConstantError|StreamWrongLastSequenceConstant"
  "NewJSTempStorageFailedError|TempStorageFailed"
  "NewJSTemplateNameNotMatchSubjectError|TemplateNameNotMatchSubject"
)

templated_methods=(
  "NewJSAtomicPublishTooLargeBatchError|object?|size|AtomicPublishTooLargeBatch|{size}"
  "NewJSAtomicPublishUnsupportedHeaderBatchError|object?|header|AtomicPublishUnsupportedHeaderBatch|{header}"
  "NewJSClusterNoPeersError|Exception|err|ClusterNoPeers|{err}"
  "NewJSConsumerCreateError|Exception|err|ConsumerCreateErr|{err}"
  "NewJSConsumerDescriptionTooLongError|object?|max|ConsumerDescriptionTooLong|{max}"
  "NewJSConsumerInactiveThresholdExcessError|object?|limit|ConsumerInactiveThresholdExcess|{limit}"
  "NewJSConsumerInvalidPolicyError|Exception|err|ConsumerInvalidPolicy|{err}"
  "NewJSConsumerInvalidResetError|Exception|err|ConsumerInvalidReset|{err}"
  "NewJSConsumerInvalidSamplingError|Exception|err|ConsumerInvalidSampling|{err}"
  "NewJSConsumerMaxPendingAckExcessError|object?|limit|ConsumerMaxPendingAckExcess|{limit}"
  "NewJSConsumerMaxRequestBatchExceededError|object?|limit|ConsumerMaxRequestBatchExceeded|{limit}"
  "NewJSConsumerMetadataLengthError|object?|limit|ConsumerMetadataLength|{limit}"
  "NewJSConsumerNameTooLongError|object?|max|ConsumerNameTooLong|{max}"
  "NewJSConsumerOfflineReasonError|Exception|err|ConsumerOfflineReason|{err}"
  "NewJSConsumerStoreFailedError|Exception|err|ConsumerStoreFailed|{err}"
  "NewJSInvalidJSONError|Exception|err|InvalidJSON|{err}"
  "NewJSMirrorConsumerSetupFailedError|Exception|err|MirrorConsumerSetupFailed|{err}"
  "NewJSMirrorInvalidSubjectFilterError|Exception|err|MirrorInvalidSubjectFilter|{err}"
  "NewJSMirrorInvalidTransformDestinationError|Exception|err|MirrorInvalidTransformDestination|{err}"
  "NewJSPedanticError|Exception|err|Pedantic|{err}"
  "NewJSRaftGeneralError|Exception|err|RaftGeneralErr|{err}"
  "NewJSSequenceNotFoundError|ulong|seq|SequenceNotFound|{seq}"
  "NewJSSourceConsumerSetupFailedError|Exception|err|SourceConsumerSetupFailed|{err}"
  "NewJSSourceInvalidSubjectFilterError|Exception|err|SourceInvalidSubjectFilter|{err}"
  "NewJSSourceInvalidTransformDestinationError|Exception|err|SourceInvalidTransformDestination|{err}"
  "NewJSStreamAssignmentError|Exception|err|StreamAssignment|{err}"
  "NewJSStreamCreateError|Exception|err|StreamCreate|{err}"
  "NewJSStreamDeleteError|Exception|err|StreamDelete|{err}"
  "NewJSStreamGeneralError|Exception|err|StreamGeneralError|{err}"
  "NewJSStreamInvalidConfigError|Exception|err|StreamInvalidConfig|{err}"
  "NewJSStreamInvalidExternalDeliverySubjError|object?|prefix|StreamInvalidExternalDeliverySubj|{prefix}"
  "NewJSStreamLimitsError|Exception|err|StreamLimits|{err}"
  "NewJSStreamMoveInProgressError|object?|msg|StreamMoveInProgress|{msg}"
  "NewJSStreamMsgDeleteFailedError|Exception|err|StreamMsgDeleteFailed|{err}"
  "NewJSStreamOfflineReasonError|Exception|err|StreamOfflineReason|{err}"
  "NewJSStreamPurgeFailedError|Exception|err|StreamPurgeFailed|{err}"
  "NewJSStreamRollupFailedError|Exception|err|StreamRollupFailed|{err}"
  "NewJSStreamSnapshotError|Exception|err|StreamSnapshot|{err}"
  "NewJSStreamStoreFailedError|Exception|err|StreamStoreFailed|{err}"
  "NewJSStreamTemplateCreateError|Exception|err|StreamTemplateCreate|{err}"
  "NewJSStreamTemplateDeleteError|Exception|err|StreamTemplateDelete|{err}"
  "NewJSStreamTransformInvalidDestinationError|Exception|err|StreamTransformInvalidDestination|{err}"
  "NewJSStreamTransformInvalidSourceError|Exception|err|StreamTransformInvalidSource|{err}"
  "NewJSStreamUpdateError|Exception|err|StreamUpdate|{err}"
  "NewJSStreamWrongLastMsgIDError|object?|id|StreamWrongLastMsgID|{id}"
  "NewJSStreamWrongLastSequenceError|ulong|seq|StreamWrongLastSequence|{seq}"
)

templated_methods_two_args=(
  "NewJSStreamExternalApiOverlapError|object?|prefix|object?|subject|StreamExternalApiOverlap|{prefix}|{subject}"
  "NewJSStreamExternalDelPrefixOverlapsError|object?|prefix|object?|subject|StreamExternalDelPrefixOverlaps|{prefix}|{subject}"
)

{
  cat <<'EOF'
// Copyright 2020-2026 The NATS Authors
// Licensed under the Apache License, Version 2.0 (the "License");
//
// Generated constructor surface for JetStream API errors.
// Source parity: server/jetstream_errors_generated.go

namespace ZB.MOM.NatsNet.Server;

public static partial class JsApiErrors
{
EOF

  for entry in "${simple_methods[@]}"; do
    IFS='|' read -r method field <<<"$entry"
    cat <<EOF
    public static JsApiError ${method}(params ErrorOption[] opts)
    {
        if (ParseOpts(opts) is JsApiError overridden)
            return Clone(overridden);

        return Clone(${field});
    }

EOF
  done

  for entry in "${templated_methods[@]}"; do
    IFS='|' read -r method arg_type arg_name field placeholder <<<"$entry"
    cat <<EOF
    public static JsApiError ${method}(${arg_type} ${arg_name}, params ErrorOption[] opts)
    {
        if (ParseOpts(opts) is JsApiError overridden)
            return Clone(overridden);

        return NewWithTags(${field}, "${placeholder}", ${arg_name});
    }

EOF
  done

  for entry in "${templated_methods_two_args[@]}"; do
    IFS='|' read -r method arg1_type arg1_name arg2_type arg2_name field placeholder1 placeholder2 <<<"$entry"
    cat <<EOF
    public static JsApiError ${method}(${arg1_type} ${arg1_name}, ${arg2_type} ${arg2_name}, params ErrorOption[] opts)
    {
        if (ParseOpts(opts) is JsApiError overridden)
            return Clone(overridden);

        return NewWithTags(${field}, "${placeholder1}", ${arg1_name}, "${placeholder2}", ${arg2_name});
    }

EOF
  done

  cat <<'EOF'
}
EOF
} >"$output_file"

echo "Generated $output_file"
