package mapping

import (
	commonsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/commonv1"
	semantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/layoutauthoringv1"
	layoutauthoringv2 "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/layoutauthoringv2"
	adminreadsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/metadataadminreadv1"
	historysemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/queryv1"
	runtimev1 "github.com/pingcap-inc/nexuscrm-contract/wire-go/gen/runtime/v1"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/reflect/protoreflect"
)

// These floors use the root semantic grammar rather than protobuf byte size.
// A zero semantic node is no larger than any populated instance of the same
// node. Callers charge a repeated semantic entry exactly once, so the sum is a
// conservative lower bound of the mapped semantic graph.
var layoutAuthoringSemanticFloors = struct {
	document, section, fieldLabel, behaviorGroup, behavior int
	relatedList, prefillMapping, recordPanel, action       int
	recordState, banner, link, actionOverride, readOnly    int
	namedValue, value, layoutSummary, assignmentSummary    int
	storedLayoutSummary, storedAssignment, storedDimension int
	stringValue, createContext                             int
}{
	document:            semantic.SemanticResponseSize(semantic.LayoutDocument{}),
	section:             semantic.SemanticResponseSize(semantic.LayoutSection{}),
	fieldLabel:          semantic.SemanticResponseSize(semantic.FieldLabel{}),
	behaviorGroup:       semantic.SemanticResponseSize(semantic.FieldBehaviorGroup{}),
	behavior:            semantic.SemanticResponseSize(semantic.FieldBehavior{}),
	relatedList:         semantic.SemanticResponseSize(semantic.RelatedList{}),
	prefillMapping:      semantic.SemanticResponseSize(semantic.PrefillMapping{}),
	recordPanel:         semantic.SemanticResponseSize(semantic.RecordPanel{}),
	action:              semantic.SemanticResponseSize(semantic.LayoutAction{}),
	recordState:         semantic.SemanticResponseSize(semantic.RecordStateRule{}),
	banner:              semantic.SemanticResponseSize(semantic.RecordStateBanner{}),
	link:                semantic.SemanticResponseSize(semantic.RecordStateLink{}),
	actionOverride:      semantic.SemanticResponseSize(semantic.RecordStateActionOverride{}),
	readOnly:            semantic.SemanticResponseSize(semantic.RecordStateReadOnly{}),
	namedValue:          semantic.SemanticResponseSize(semantic.NamedValue{}),
	value:               semantic.SemanticResponseSize(semantic.Value{}),
	layoutSummary:       semantic.SemanticResponseSize(semantic.LayoutSummary{}),
	assignmentSummary:   semantic.SemanticResponseSize(semantic.LayoutAssignmentSummary{}),
	storedLayoutSummary: semantic.SemanticResponseSize(adminreadsemantic.LayoutSummary{}),
	storedAssignment:    semantic.SemanticResponseSize(adminreadsemantic.LayoutAssignment{}),
	storedDimension:     semantic.SemanticResponseSize(adminreadsemantic.LayoutAssignmentDimension{}),
	stringValue:         semantic.SemanticResponseSize(""),
	createContext:       semantic.SemanticResponseSize(semantic.CreateContext{}),
}

type layoutAuthoringWireBudget struct {
	response bool

	semanticRemaining int
	documentRemaining int
	documentActive    bool

	behaviorNodes int
	valueNodes    int
	collections   int
}

func newLayoutAuthoringWireBudget(response bool) *layoutAuthoringWireBudget {
	maximum := semantic.MaxSemanticRequestBytes
	if response {
		maximum = semantic.MaxSemanticResponseBytes
	}
	return &layoutAuthoringWireBudget{response: response, semanticRemaining: maximum}
}

func newLayoutAuthoringResponseWireBudget() *layoutAuthoringWireBudget {
	return newLayoutAuthoringWireBudget(true)
}

func (budget *layoutAuthoringWireBudget) fail(kind commonsemantic.LimitKind, maximum int) error {
	if budget.response {
		return internalPlatformWire()
	}
	return platformLimitFailure(kind, maximum)
}

func (budget *layoutAuthoringWireBudget) malformed() error {
	if budget.response {
		return internalPlatformWire()
	}
	return invalidPlatformWire()
}

func (budget *layoutAuthoringWireBudget) takeSemanticFloor(size int) error {
	return budget.takeSemanticFloorCount(size, 1)
}

func (budget *layoutAuthoringWireBudget) takeSemanticFloorCount(size, count int) error {
	if size < 0 || count < 0 || (size != 0 && count > budget.semanticRemaining/size) {
		kind := commonsemantic.LimitSemanticRequest
		maximum := semantic.MaxSemanticRequestBytes
		if budget.response {
			kind = commonsemantic.LimitSemanticResponse
			maximum = semantic.MaxSemanticResponseBytes
		}
		return budget.fail(kind, maximum)
	}
	total := size * count
	budget.semanticRemaining -= total
	if budget.documentActive {
		if total > budget.documentRemaining {
			return budget.fail(commonsemantic.LimitSemanticRequest, semantic.MaxLayoutDocumentSemanticBytes)
		}
		budget.documentRemaining -= total
	}
	return nil
}

func (budget *layoutAuthoringWireBudget) withinDocument(visit func() error) error {
	if budget.documentActive {
		return budget.malformed()
	}
	budget.documentActive = true
	budget.documentRemaining = semantic.MaxLayoutDocumentSemanticBytes
	defer func() {
		budget.documentActive = false
		budget.documentRemaining = 0
	}()
	if err := budget.takeSemanticFloor(layoutAuthoringSemanticFloors.document); err != nil {
		return err
	}
	return visit()
}

type layoutAuthoringRepeatedPolicy struct {
	maximum       int
	kind          commonsemantic.LimitKind
	semanticFloor int
	behaviorNodes bool
}

func layoutAuthoringField(message, field string) protoreflect.FullName {
	return protoreflect.FullName("nexuscrm.runtime.v1." + message + "." + field)
}

// Every repeated field in layout_authoring.proto is registered here. The
// exhaustive descriptor test fails when the schema grows without admission
// policy. LayoutAuthoringStringList.values is context-bound because the same
// wrapper carries several independently limited semantic collections.
var layoutAuthoringRepeatedPolicies = map[protoreflect.FullName]layoutAuthoringRepeatedPolicy{
	layoutAuthoringField("LayoutAuthoringCreateContext", "required_fields"):                       {semantic.MaxCreateRequiredFields, commonsemantic.LimitFieldCount, layoutAuthoringSemanticFloors.stringValue, false},
	layoutAuthoringField("LayoutAuthoringLayoutSnapshot", "ordered_list_fields"):                  {semantic.MaxListFields, commonsemantic.LimitFieldCount, layoutAuthoringSemanticFloors.stringValue, false},
	layoutAuthoringField("LayoutAuthoringServiceReadWorkspaceResponse", "layouts"):                {semantic.MaxWorkspaceLayouts, commonsemantic.LimitRecordCount, layoutAuthoringSemanticFloors.layoutSummary, false},
	layoutAuthoringField("LayoutAuthoringServiceReadWorkspaceResponse", "assignments"):            {semantic.MaxWorkspaceAssignments, commonsemantic.LimitRecordCount, layoutAuthoringSemanticFloors.assignmentSummary, false},
	layoutAuthoringField("LayoutAuthoringServiceReadStoredLayoutResponse", "ordered_list_fields"): {semantic.MaxListFields, commonsemantic.LimitFieldCount, layoutAuthoringSemanticFloors.stringValue, false},
	layoutAuthoringField("LayoutAuthoringDocument", "compact_fields"):                             {semantic.MaxCompactFields, commonsemantic.LimitFieldCount, layoutAuthoringSemanticFloors.stringValue, false},
	layoutAuthoringField("LayoutAuthoringDocument", "tabs"):                                       {semantic.MaxTabs, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.stringValue, false},
	layoutAuthoringField("LayoutAuthoringDocument", "sections"):                                   {semantic.MaxSections, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.section, false},
	layoutAuthoringField("LayoutAuthoringDocument", "related_lists"):                              {semantic.MaxRelatedLists, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.relatedList, false},
	layoutAuthoringField("LayoutAuthoringDocument", "record_panels"):                              {semantic.MaxRecordPanels, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.recordPanel, false},
	layoutAuthoringField("LayoutAuthoringDocument", "record_states"):                              {semantic.MaxRecordStates, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.recordState, false},
	layoutAuthoringField("LayoutAuthoringDocument", "primary_header_actions"):                     {semantic.MaxPrimaryHeaderActions, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.stringValue, false},
	layoutAuthoringField("LayoutAuthoringSection", "component_configuration"):                     {semantic.MaxConfigurationEntries, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.namedValue, false},
	layoutAuthoringField("LayoutAuthoringSection", "fields"):                                      {semantic.MaxFieldsPerSection, commonsemantic.LimitFieldCount, layoutAuthoringSemanticFloors.stringValue, false},
	layoutAuthoringField("LayoutAuthoringSection", "field_labels"):                                {semantic.MaxFieldLabelsPerSection, commonsemantic.LimitFieldCount, layoutAuthoringSemanticFloors.fieldLabel, false},
	layoutAuthoringField("LayoutAuthoringSection", "field_behaviors"):                             {semantic.MaxFieldBehaviorGroupsPerSection, commonsemantic.LimitFieldCount, layoutAuthoringSemanticFloors.behaviorGroup, true},
	layoutAuthoringField("LayoutAuthoringFieldBehaviorList", "values"):                            {semantic.MaxFieldBehaviorsPerField, commonsemantic.LimitFieldCount, layoutAuthoringSemanticFloors.behavior, true},
	layoutAuthoringField("LayoutAuthoringRelatedList", "field_ids"):                               {semantic.MaxFieldsPerRelatedList, commonsemantic.LimitFieldCount, layoutAuthoringSemanticFloors.stringValue, false},
	layoutAuthoringField("LayoutAuthoringRelatedList", "prefill_mappings"):                        {semantic.MaxPrefillMappings, commonsemantic.LimitFieldCount, layoutAuthoringSemanticFloors.prefillMapping, false},
	layoutAuthoringField("LayoutAuthoringRecordPanel", "renderer_configuration"):                  {semantic.MaxConfigurationEntries, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.namedValue, false},
	layoutAuthoringField("LayoutAuthoringActionPlacement", "actions"):                             {semantic.MaxActionsPerPlacement, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.action, false},
	layoutAuthoringField("LayoutAuthoringAction", "configuration"):                                {semantic.MaxConfigurationEntries, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.namedValue, false},
	layoutAuthoringField("LayoutAuthoringAction", "extensions"):                                   {semantic.MaxActionExtensions, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.namedValue, false},
	layoutAuthoringField("LayoutAuthoringRecordStateBanner", "link_ids"):                          {semantic.MaxRecordStateLinks, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.stringValue, false},
	layoutAuthoringField("LayoutAuthoringRecordStateRule", "links"):                               {semantic.MaxRecordStateLinks, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.link, false},
	layoutAuthoringField("LayoutAuthoringRecordStateRule", "action_overrides"):                    {semantic.MaxRecordStateActionOverrides, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.actionOverride, false},
	layoutAuthoringField("LayoutAuthoringValueList", "values"):                                    {semantic.MaxValueCollectionEntries, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.value, false},
	layoutAuthoringField("LayoutAuthoringNamedValueList", "values"):                               {semantic.MaxValueCollectionEntries, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.namedValue, false},
	layoutAuthoringField("LayoutAuthoringSectionList", "values"):                                  {semantic.MaxSections, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.section, false},
	layoutAuthoringField("LayoutAuthoringRelatedListList", "values"):                              {semantic.MaxRelatedLists, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.relatedList, false},
	layoutAuthoringField("LayoutAuthoringRecordPanelList", "values"):                              {semantic.MaxRecordPanels, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.recordPanel, false},
	layoutAuthoringField("LayoutAuthoringRecordStateRuleList", "values"):                          {semantic.MaxRecordStates, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.recordState, false},
}

var layoutAuthoringContextualStringListPolicies = map[protoreflect.FullName]layoutAuthoringRepeatedPolicy{
	layoutAuthoringField("LayoutAuthoringCreateLayout", "list_fields"):               {semantic.MaxListFields, commonsemantic.LimitFieldCount, layoutAuthoringSemanticFloors.stringValue, false},
	layoutAuthoringField("LayoutAuthoringUpdateLayout", "list_fields"):               {semantic.MaxListFields, commonsemantic.LimitFieldCount, layoutAuthoringSemanticFloors.stringValue, false},
	layoutAuthoringField("LayoutAuthoringDocumentChanges", "compact_fields"):         {semantic.MaxCompactFields, commonsemantic.LimitFieldCount, layoutAuthoringSemanticFloors.stringValue, false},
	layoutAuthoringField("LayoutAuthoringDocumentChanges", "tabs"):                   {semantic.MaxTabs, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.stringValue, false},
	layoutAuthoringField("LayoutAuthoringDocumentChanges", "primary_header_actions"): {semantic.MaxPrimaryHeaderActions, commonsemantic.LimitOperationCount, layoutAuthoringSemanticFloors.stringValue, false},
}

var layoutAuthoringSingularFloors = map[protoreflect.FullName]int{
	layoutAuthoringField("LayoutAuthoringServiceReadStoredLayoutResponse", "create_context"): layoutAuthoringSemanticFloors.createContext,
	layoutAuthoringField("LayoutAuthoringRecordStateRule", "banner"):                         layoutAuthoringSemanticFloors.banner,
	layoutAuthoringField("LayoutAuthoringRecordStateRule", "read_only"):                      layoutAuthoringSemanticFloors.readOnly,
}

// These repeated message elements contain no nested collection or recursive
// message that admission needs to inspect. Their collection is already
// checked and charged in bulk, so descending would only materialize one
// protoreflect wrapper per attacker-controlled element.
var layoutAuthoringAdmissionLeafMessages = map[protoreflect.FullName]struct{}{
	"nexuscrm.runtime.v1.LayoutAuthoringLayoutSummary":             {},
	"nexuscrm.runtime.v1.LayoutAuthoringAssignmentSummary":         {},
	"nexuscrm.runtime.v1.LayoutAuthoringFieldLabel":                {},
	"nexuscrm.runtime.v1.LayoutAuthoringFieldBehavior":             {},
	"nexuscrm.runtime.v1.LayoutAuthoringPrefillMapping":            {},
	"nexuscrm.runtime.v1.LayoutAuthoringRecordStateLink":           {},
	"nexuscrm.runtime.v1.LayoutAuthoringRecordStateActionOverride": {},
}

type layoutAuthoringVisitContext struct {
	valueDepth       int
	stringListPolicy *layoutAuthoringRepeatedPolicy
}

func preflightWireLayoutAuthoringSubmitRequest(request *runtimev1.LayoutAuthoringServiceSubmitRequest) error {
	return preflightWireLayoutAuthoringMessage(request, newLayoutAuthoringWireBudget(false))
}

func preflightWireLayoutAuthoringSubmitResponse(response *runtimev1.LayoutAuthoringServiceSubmitResponse) error {
	return preflightWireLayoutAuthoringMessage(response, newLayoutAuthoringResponseWireBudget())
}

func preflightWireLayoutAuthoringCommandStatus(response *runtimev1.LayoutAuthoringServiceGetCommandResponse) error {
	return preflightWireLayoutAuthoringMessage(response, newLayoutAuthoringResponseWireBudget())
}

func preflightWireLayoutAuthoringWorkspace(response *runtimev1.LayoutAuthoringServiceReadWorkspaceResponse) error {
	return preflightWireLayoutAuthoringMessage(response, newLayoutAuthoringResponseWireBudget())
}

func preflightWireLayoutAuthoringStoredLayout(response *runtimev1.LayoutAuthoringServiceReadStoredLayoutResponse) error {
	return preflightWireLayoutAuthoringMessage(response, newLayoutAuthoringResponseWireBudget())
}

func preflightWireLayoutAuthoringV2MutateRequest(request *runtimev1.LayoutAuthoringV2ServiceMutateRequest) error {
	if request != nil {
		if len(request.GetHistoryRelatedLists()) > layoutauthoringv2.MaxHistoryRelatedListProjections {
			return platformLimitFailure(commonsemantic.LimitOperationCount, layoutauthoringv2.MaxHistoryRelatedListProjections)
		}
		for _, projection := range request.GetHistoryRelatedLists() {
			if len(projection.GetColumns()) > historysemantic.HistoryResultColumnCount {
				return platformLimitFailure(commonsemantic.LimitFieldCount, historysemantic.HistoryResultColumnCount)
			}
			if projection == nil || len(projection.GetColumns()) != historysemantic.HistoryResultColumnCount {
				return invalidPlatformWire()
			}
		}
	}

	budget := newLayoutAuthoringWireBudget(false)
	if request == nil {
		return budget.malformed()
	}
	switch operation := request.Operation.(type) {
	case *runtimev1.LayoutAuthoringV2ServiceMutateRequest_Create:
		if operation.Create == nil {
			return budget.malformed()
		}
		if err := preflightWireLayoutAuthoringMessage(operation.Create.GetDocument(), budget); err != nil {
			return err
		}
		return preflightWireLayoutAuthoringV2ListChange(operation.Create.GetListFields(), budget)
	case *runtimev1.LayoutAuthoringV2ServiceMutateRequest_Update:
		if operation.Update == nil {
			return budget.malformed()
		}
		if err := preflightWireLayoutAuthoringMessage(operation.Update.GetChanges(), budget); err != nil {
			return err
		}
		return preflightWireLayoutAuthoringV2ListChange(operation.Update.GetListFields(), budget)
	default:
		return nil
	}
}

func preflightWireLayoutAuthoringV2ListChange(change *runtimev1.LayoutAuthoringStringListChange, budget *layoutAuthoringWireBudget) error {
	if change == nil {
		return budget.malformed()
	}
	if change.Value == nil {
		return nil
	}
	values := change.Value.GetValues()
	if len(values) > semantic.MaxListFields {
		return budget.fail(commonsemantic.LimitFieldCount, semantic.MaxListFields)
	}
	return budget.takeSemanticFloorCount(layoutAuthoringSemanticFloors.stringValue, len(values))
}

func preflightWireLayoutAuthoringV2Workspace(response *runtimev1.LayoutAuthoringV2ServiceReadWorkspaceResponse) error {
	budget := newLayoutAuthoringResponseWireBudget()
	if response == nil {
		return budget.malformed()
	}
	if len(response.GetLayouts()) > adminreadsemantic.MaxLayoutsPerObject {
		return budget.fail(commonsemantic.LimitRecordCount, adminreadsemantic.MaxLayoutsPerObject)
	}
	if err := budget.takeSemanticFloorCount(layoutAuthoringSemanticFloors.storedLayoutSummary, len(response.GetLayouts())); err != nil {
		return err
	}
	if len(response.GetAssignments()) > adminreadsemantic.MaxAssignmentsPerObject {
		return budget.fail(commonsemantic.LimitRecordCount, adminreadsemantic.MaxAssignmentsPerObject)
	}
	if err := budget.takeSemanticFloorCount(layoutAuthoringSemanticFloors.storedAssignment, len(response.GetAssignments())); err != nil {
		return err
	}
	for _, assignment := range response.GetAssignments() {
		if assignment == nil || len(assignment.GetDimensions()) > adminreadsemantic.MaxAssignmentDimensions {
			return budget.malformed()
		}
		if err := budget.takeSemanticFloorCount(layoutAuthoringSemanticFloors.storedDimension, len(assignment.GetDimensions())); err != nil {
			return err
		}
		for _, dimension := range assignment.GetDimensions() {
			if dimension == nil {
				return budget.malformed()
			}
		}
	}
	return nil
}

func preflightWireLayoutAuthoringV2StoredLayout(response *runtimev1.LayoutAuthoringV2ServiceReadStoredLayoutResponse) error {
	budget := newLayoutAuthoringResponseWireBudget()
	if response == nil {
		return budget.malformed()
	}
	if err := preflightWireLayoutAuthoringMessage(response.GetDocument(), budget); err != nil {
		return err
	}
	if response.GetOrderedListFields() == nil || response.GetRequiredCreateFields() == nil {
		return budget.malformed()
	}
	orderedFields := response.GetOrderedListFields().GetValues()
	if len(orderedFields) > semantic.MaxListFields {
		return budget.fail(commonsemantic.LimitFieldCount, semantic.MaxListFields)
	}
	if err := budget.takeSemanticFloorCount(layoutAuthoringSemanticFloors.stringValue, len(orderedFields)); err != nil {
		return err
	}
	requiredFields := response.GetRequiredCreateFields().GetValues()
	if len(requiredFields) > semantic.MaxCreateRequiredFields {
		return budget.fail(commonsemantic.LimitFieldCount, semantic.MaxCreateRequiredFields)
	}
	return budget.takeSemanticFloorCount(layoutAuthoringSemanticFloors.stringValue, len(requiredFields))
}

func preflightWireLayoutAuthoringMessage(message proto.Message, budget *layoutAuthoringWireBudget) error {
	if message == nil || !message.ProtoReflect().IsValid() {
		return budget.malformed()
	}
	return visitWireLayoutAuthoringMessage(message.ProtoReflect(), layoutAuthoringVisitContext{}, budget)
}

func visitWireLayoutAuthoringMessage(message protoreflect.Message, context layoutAuthoringVisitContext, budget *layoutAuthoringWireBudget) error {
	if !message.IsValid() {
		return budget.malformed()
	}
	descriptor := message.Descriptor()
	if descriptor.FullName() == "nexuscrm.runtime.v1.LayoutAuthoringDocument" {
		return budget.withinDocument(func() error {
			return visitWireLayoutAuthoringMessageFields(message, context, budget)
		})
	}
	if descriptor.FullName() == "nexuscrm.runtime.v1.LayoutAuthoringValue" {
		if context.valueDepth == 0 {
			context.valueDepth = 1
		}
		budget.valueNodes++
		if budget.valueNodes > semantic.MaxValueNodes {
			return budget.fail(commonsemantic.LimitOperationCount, semantic.MaxValueNodes)
		}
		if context.valueDepth > semantic.MaxValueDepth {
			return budget.fail(commonsemantic.LimitQueryDepth, semantic.MaxValueDepth)
		}
	}
	return visitWireLayoutAuthoringMessageFields(message, context, budget)
}

func visitWireLayoutAuthoringMessageFields(message protoreflect.Message, context layoutAuthoringVisitContext, budget *layoutAuthoringWireBudget) error {
	var visitErr error
	message.Range(func(field protoreflect.FieldDescriptor, value protoreflect.Value) bool {
		fieldName := field.FullName()
		if field.IsList() {
			policy, known := layoutAuthoringRepeatedPolicies[fieldName]
			if fieldName == layoutAuthoringField("LayoutAuthoringStringList", "values") {
				if context.stringListPolicy == nil {
					visitErr = budget.malformed()
					return false
				}
				policy = *context.stringListPolicy
				known = true
			}
			if !known {
				visitErr = budget.malformed()
				return false
			}
			list := value.List()
			if list.Len() > policy.maximum {
				visitErr = budget.fail(policy.kind, policy.maximum)
				return false
			}
			if policy.behaviorNodes {
				budget.behaviorNodes += list.Len()
				if budget.behaviorNodes > semantic.MaxFieldBehaviorNodesPerDocument {
					visitErr = budget.fail(commonsemantic.LimitFieldCount, semantic.MaxFieldBehaviorNodesPerDocument)
					return false
				}
			}
			if err := budget.takeSemanticFloorCount(policy.semanticFloor, list.Len()); err != nil {
				visitErr = err
				return false
			}
			if fieldName == layoutAuthoringField("LayoutAuthoringCreateContext", "required_fields") {
				// Whole-object names can span many sections. Charge their actual
				// bytes before mapping clones the collection; the count-only floor
				// above cannot enforce the existing response budget on its own.
				for index := 0; index < list.Len(); index++ {
					length := len(list.Get(index).String())
					if length == 0 || length > commonsemantic.MaxFieldIdentifierBytes {
						visitErr = budget.malformed()
						return false
					}
					if err := budget.takeSemanticFloor(length); err != nil {
						visitErr = err
						return false
					}
				}
			}
			if field.Message() == nil {
				return true
			}
			if _, leaf := layoutAuthoringAdmissionLeafMessages[field.Message().FullName()]; leaf {
				return true
			}
			for index := 0; index < list.Len(); index++ {
				child := list.Get(index).Message()
				if !child.IsValid() {
					visitErr = budget.malformed()
					return false
				}
				if err := visitWireLayoutAuthoringMessage(child, context, budget); err != nil {
					visitErr = err
					return false
				}
			}
			return true
		}
		if field.Message() == nil {
			return true
		}
		childContext := context
		if policy, contextual := layoutAuthoringContextualStringListPolicies[fieldName]; contextual {
			childContext.stringListPolicy = &policy
		}
		if message.Descriptor().FullName() == "nexuscrm.runtime.v1.LayoutAuthoringValue" &&
			(fieldName == layoutAuthoringField("LayoutAuthoringValue", "list_value") ||
				fieldName == layoutAuthoringField("LayoutAuthoringValue", "object_value")) {
			budget.collections++
			if budget.collections > semantic.MaxValueCollections {
				visitErr = budget.fail(commonsemantic.LimitOperationCount, semantic.MaxValueCollections)
				return false
			}
			childContext.valueDepth = context.valueDepth + 1
		}
		if floor := layoutAuthoringSingularFloors[fieldName]; floor != 0 {
			if err := budget.takeSemanticFloor(floor); err != nil {
				visitErr = err
				return false
			}
		}
		child := value.Message()
		if !child.IsValid() {
			visitErr = budget.malformed()
			return false
		}
		if err := visitWireLayoutAuthoringMessage(child, childContext, budget); err != nil {
			visitErr = err
			return false
		}
		return true
	})
	return visitErr
}
