package runtimegrpc

import (
	"errors"
	"time"
)

// RuntimeClientOption configures additive client behavior without changing the
// released RuntimeClientConfig struct layout. The interface is sealed so only
// options reviewed by this transport owner can mutate client policy.
type RuntimeClientOption interface {
	applyRuntimeClientOption(*runtimeClientOptions) error
}

type runtimeClientOptionFunc func(*runtimeClientOptions) error

func (option runtimeClientOptionFunc) applyRuntimeClientOption(options *runtimeClientOptions) error {
	return option(options)
}

type runtimeClientOptions struct {
	recordMutationAdmissionRetryBudget time.Duration
}

// WithRecordMutationAdmissionRetryBudget bounds direct Record Mutation retries
// explicitly authorized by a fail-fast Runtime ADMISSION response. Zero keeps
// retries disabled. The original parent context remains the route deadline.
func WithRecordMutationAdmissionRetryBudget(budget time.Duration) RuntimeClientOption {
	return runtimeClientOptionFunc(func(options *runtimeClientOptions) error {
		if budget < 0 {
			return errors.New("runtime client: admission retry budget must not be negative")
		}
		options.recordMutationAdmissionRetryBudget = budget
		return nil
	})
}

func resolveRuntimeClientOptions(values ...RuntimeClientOption) (runtimeClientOptions, error) {
	var options runtimeClientOptions
	for _, value := range values {
		if value == nil {
			return runtimeClientOptions{}, errors.New("runtime client: option is required")
		}
		if err := value.applyRuntimeClientOption(&options); err != nil {
			return runtimeClientOptions{}, err
		}
	}
	return options, nil
}
