package runtimegrpc

import (
	"context"

	"google.golang.org/grpc/metadata"
)

// RequestIDMetadataKey carries non-authoritative request correlation across the
// private Runtime transport. It must never participate in authentication,
// authorization, admission, compatibility, retry, or idempotency decisions.
const RequestIDMetadataKey = "x-nexuscrm-request-id"

const maxRequestIDBytes = 128

// WithRequestID replaces any existing outgoing request correlation with value.
// Invalid values are removed instead of being forwarded across the trust
// boundary. The caller's other outgoing metadata is preserved.
func WithRequestID(ctx context.Context, value string) context.Context {
	values, _ := metadata.FromOutgoingContext(ctx)
	values = values.Copy()
	values.Delete(RequestIDMetadataKey)
	if validRequestID(value) {
		values.Set(RequestIDMetadataKey, value)
	}
	return metadata.NewOutgoingContext(ctx, values)
}

// IncomingRequestID returns the single valid request correlation value on an
// admitted gRPC request. Multiple or malformed values are rejected rather than
// selected ambiguously.
func IncomingRequestID(ctx context.Context) (string, bool) {
	values, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return "", false
	}
	requestIDs := values.Get(RequestIDMetadataKey)
	if len(requestIDs) != 1 || !validRequestID(requestIDs[0]) {
		return "", false
	}
	return requestIDs[0], true
}

func validRequestID(value string) bool {
	if len(value) == 0 || len(value) > maxRequestIDBytes {
		return false
	}
	for i := 0; i < len(value); i++ {
		character := value[i]
		if (character >= 'a' && character <= 'z') ||
			(character >= 'A' && character <= 'Z') ||
			(character >= '0' && character <= '9') {
			continue
		}
		switch character {
		case '-', '_', '.', ':':
			continue
		default:
			return false
		}
	}
	return true
}
