package catalogreconcile

import (
	"context"
	"encoding/json"
	"fmt"
	"sort"
	"strings"

	"github.com/expr-lang/expr/ast"
	"github.com/nexuscrm/kernel/pkg/formula"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
	"github.com/nexuscrm/shared/pkg/searchmetadata"
	consumerv1 "github.com/pingcap-inc/nexuscrm-contract/pkg/catalog/consumerv1"
	controlplane "github.com/pingcap-inc/nexuscrm-controlplane"
	"github.com/pingcap-inc/nexuscrm-controlplane/catalogapp"
	"github.com/pingcap-inc/nexuscrm-controlplane/packs"
)

const (
	// Format 2 adds the sparse unique field fact. It remains the current V2
	// capability grammar and a historical V3 grammar.
	effectiveObjectSearchComponentFormatV2 uint32 = 2
	// Format 3 adds the sparse object pathField fact. Keeping format 2 would let
	// an older strict L1 decoder accept a component that cannot serve the Path UI
	// contract instead of failing closed on an unsupported projection.
	effectiveObjectSearchComponentFormatV3 uint32 = 3
	// Format 4 adds ordered object listFields, sparse formula bodies, typed
	// picklist value-domain sources, and sparse sibling-MAX parent fields. The
	// source lineage is derived by L0 from the formula AST so L1 never needs to
	// reinterpret authored formula text.
	effectiveObjectSearchComponentFormatV4 uint32 = 4
	// Format 5 completes the object/field presentation facts consumed by the
	// independent AppService. These are projections of the effective schema and
	// verified AppRelease, never L1-shaped inference inside Catalog.
	effectiveObjectSearchComponentFormatV5 uint32 = 5
	// Format 6 carries the Records-owned static create-input requirements.
	// Presence distinguishes an empty requirement set from historical metadata
	// that cannot answer this question.
	effectiveObjectSearchComponentFormatV6 uint32 = 6
)

type searchAllDefaultFieldsDeclaration struct {
	ObjectAPIName string   `json:"objectApiName"`
	Fields        []string `json:"fields"`
}

type effectiveObjectSearchDocument struct {
	Objects []effectiveObjectSearchObject `json:"objects"`
}

type effectiveObjectSearchObject struct {
	APIName                string                       `json:"apiName"`
	KeyPrefix              string                       `json:"keyPrefix,omitempty"`
	Label                  string                       `json:"label"`
	PluralLabel            string                       `json:"pluralLabel,omitempty"`
	DisplayNameField       string                       `json:"displayNameField,omitempty"`
	PathField              string                       `json:"pathField,omitempty"`
	ListFields             *[]string                    `json:"listFields,omitempty"`
	TableType              string                       `json:"tableType"`
	Searchable             bool                         `json:"searchable"`
	SharingModel           string                       `json:"sharingModel,omitempty"`
	SharingParentObject    string                       `json:"sharingParentObject,omitempty"`
	SharingParentField     string                       `json:"sharingParentField,omitempty"`
	EnableHierarchySharing bool                         `json:"enableHierarchySharing,omitempty"`
	SearchAllDefaultFields []string                     `json:"searchAllDefaultFields,omitempty"`
	CreateRequiredFields   *[]string                    `json:"createRequiredFields,omitempty"`
	Fields                 []effectiveObjectSearchField `json:"fields"`
}

type effectiveObjectSearchFieldIdentity struct {
	apiName string
	typeID  models.FieldType
}

type effectiveObjectSearchField struct {
	APIName               string                             `json:"apiName"`
	Label                 string                             `json:"label"`
	Type                  string                             `json:"type"`
	ReturnType            string                             `json:"returnType,omitempty"`
	Precision             *int                               `json:"precision,omitempty"`
	Scale                 *int                               `json:"scale,omitempty"`
	Required              bool                               `json:"required,omitempty"`
	Unique                bool                               `json:"unique,omitempty"`
	DefaultedOnCreate     bool                               `json:"defaultedOnCreate,omitempty"`
	Createable            bool                               `json:"createable"`
	Updateable            bool                               `json:"updateable"`
	DefaultValue          *string                            `json:"defaultValue,omitempty"`
	IsNameField           bool                               `json:"isNameField,omitempty"`
	IsSystem              bool                               `json:"isSystem,omitempty"`
	CompoundFieldName     string                             `json:"compoundFieldName,omitempty"`
	CompoundComponentRole string                             `json:"compoundComponentRole,omitempty"`
	ReferenceTo           []string                           `json:"referenceTo,omitempty"`
	IsPolymorphic         bool                               `json:"isPolymorphic,omitempty"`
	RelationshipName      string                             `json:"relationshipName,omitempty"`
	ChildRelationshipName string                             `json:"childRelationshipName,omitempty"`
	DeleteRule            string                             `json:"deleteRule,omitempty"`
	IsMasterDetail        bool                               `json:"isMasterDetail,omitempty"`
	InlineHelpText        *string                            `json:"inlineHelpText,omitempty"`
	MinValue              *float64                           `json:"minValue,omitempty"`
	MaxValue              *float64                           `json:"maxValue,omitempty"`
	MinLength             *int                               `json:"minLength,omitempty"`
	MaxLength             *int                               `json:"maxLength,omitempty"`
	Options               []effectiveObjectSearchOption      `json:"options,omitempty"`
	ControllingField      string                             `json:"controllingField,omitempty"`
	PicklistDependency    map[string][]string                `json:"picklistDependency,omitempty"`
	Validator             string                             `json:"validator,omitempty"`
	ValidatorConfig       string                             `json:"validatorConfig,omitempty"`
	Formula               *string                            `json:"formula,omitempty"`
	PicklistValueSources  []effectiveObjectSearchFieldSource `json:"picklistValueSources,omitempty"`
	SiblingMaxParentField string                             `json:"siblingMaxParentField,omitempty"`
}

type effectiveObjectSearchFieldSource struct {
	Object string `json:"object"`
	Field  string `json:"field"`
}

type effectiveObjectSearchOption struct {
	Value string   `json:"value"`
	Label string   `json:"label"`
	Tags  []string `json:"tags,omitempty"`
}

type effectiveCompoundMemberRole map[string]map[string]string

func buildEffectiveObjectSearchComponent(
	objects []*models.ObjectMetadata,
	declarations []searchAllDefaultFieldsDeclaration,
	capabilityName string,
	createRequiredFields map[string][]string,
	compoundRoleSets ...effectiveCompoundMemberRole,
) (catalogapp.EffectiveMetadataComponent, error) {
	if len(compoundRoleSets) > 1 {
		return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
			"effective object-search accepts at most one compound-role authority",
		)
	}
	var compoundRoles effectiveCompoundMemberRole
	if len(compoundRoleSets) == 1 {
		compoundRoles = compoundRoleSets[0]
	}
	componentFormatVersion := uint32(0)
	switch capabilityName {
	case consumerv1.AppMetadataV2CapabilityName:
		componentFormatVersion = effectiveObjectSearchComponentFormatV2
	case consumerv1.AppMetadataV3CapabilityName:
		componentFormatVersion = effectiveObjectSearchComponentFormatV6
	default:
		return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
			"effective object-search capability %q is unsupported",
			capabilityName,
		)
	}
	return buildEffectiveObjectSearchComponentForFormat(
		objects, declarations, componentFormatVersion, createRequiredFields, compoundRoles,
	)
}

func buildEffectiveObjectSearchComponentForFormat(
	objects []*models.ObjectMetadata,
	declarations []searchAllDefaultFieldsDeclaration,
	componentFormatVersion uint32,
	createRequiredFields map[string][]string,
	compoundRoleSets ...effectiveCompoundMemberRole,
) (catalogapp.EffectiveMetadataComponent, error) {
	if len(compoundRoleSets) > 1 {
		return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
			"effective object-search accepts at most one compound-role authority",
		)
	}
	var compoundRoles effectiveCompoundMemberRole
	if len(compoundRoleSets) == 1 {
		compoundRoles = compoundRoleSets[0]
	}
	projectPathField := false
	projectListFields := false
	projectFormulaReadFacts := false
	projectPresentationFacts := false
	switch componentFormatVersion {
	case effectiveObjectSearchComponentFormatV2:
	case effectiveObjectSearchComponentFormatV3:
		projectPathField = true
	case effectiveObjectSearchComponentFormatV4:
		projectPathField = true
		projectListFields = true
		projectFormulaReadFacts = true
	case effectiveObjectSearchComponentFormatV5, effectiveObjectSearchComponentFormatV6:
		projectPathField = true
		projectListFields = true
		projectFormulaReadFacts = true
		projectPresentationFacts = true
	default:
		return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
			"effective object-search component format %d is unsupported",
			componentFormatVersion,
		)
	}
	if projectPresentationFacts {
		if err := validateEffectiveDisplayNameFields(objects); err != nil {
			return catalogapp.EffectiveMetadataComponent{}, err
		}
	}
	defaults := make(map[string][]string, len(declarations))
	for index, declaration := range declarations {
		name := strings.TrimSpace(declaration.ObjectAPIName)
		if name == "" {
			return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
				"search-all declaration[%d] has no object API name",
				index,
			)
		}
		key := strings.ToLower(name)
		if _, duplicate := defaults[key]; duplicate {
			return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
				"effective search-all declarations contain duplicate object %q",
				name,
			)
		}
		fields := append([]string(nil), declaration.Fields...)
		if len(fields) == 0 {
			return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
				"effective search-all declaration for %q has no fields",
				name,
			)
		}
		seenFields := make(map[string]struct{}, len(fields))
		for fieldIndex, rawField := range fields {
			field := strings.TrimSpace(rawField)
			fieldKey := strings.ToLower(field)
			if field == "" {
				return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
					"effective search-all declaration for %q field[%d] is blank",
					name, fieldIndex,
				)
			}
			if _, duplicate := seenFields[fieldKey]; duplicate {
				return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
					"effective search-all declaration for %q contains duplicate field %q",
					name, field,
				)
			}
			seenFields[fieldKey] = struct{}{}
			fields[fieldIndex] = field
		}
		defaults[key] = fields
	}

	document := effectiveObjectSearchDocument{
		Objects: make([]effectiveObjectSearchObject, 0, len(objects)),
	}
	seenObjects := make(map[string]struct{}, len(objects))
	for index, object := range objects {
		if object == nil {
			return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
				"effective object-search metadata[%d] is nil",
				index,
			)
		}
		name := strings.TrimSpace(object.APIName)
		key := strings.ToLower(name)
		if name == "" {
			return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
				"effective object-search metadata[%d] has no API name",
				index,
			)
		}
		if _, duplicate := seenObjects[key]; duplicate {
			return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
				"effective object-search metadata contains duplicate object %q",
				name,
			)
		}
		seenObjects[key] = struct{}{}
		canonicalDefaults, err :=
			searchmetadata.ResolveDeclaredSearchAllDefaultFieldsForSchema(
				object,
				defaults[key],
			)
		if err != nil {
			return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
				"effective search-all declaration for %q: %w",
				name,
				err,
			)
		}
		projected := effectiveObjectSearchObject{
			APIName:                name,
			Label:                  strings.TrimSpace(object.Label),
			PluralLabel:            strings.TrimSpace(object.PluralLabel),
			TableType:              strings.TrimSpace(string(object.TableType)),
			Searchable:             object.Searchable,
			SearchAllDefaultFields: canonicalDefaults,
			Fields: make(
				[]effectiveObjectSearchField, 0, len(object.Fields),
			),
		}
		if componentFormatVersion == effectiveObjectSearchComponentFormatV6 {
			fields, exists := createRequiredFields[object.APIName]
			if !exists || fields == nil {
				return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf("effective object-search create requirements for %q are unavailable", object.APIName)
			}
			projected.CreateRequiredFields = &fields
		}
		if projectPresentationFacts {
			projected.SharingModel = strings.TrimSpace(string(object.SharingModel))
			projected.EnableHierarchySharing = object.EnableHierarchySharing
			if object.SharingParentObject != nil {
				projected.SharingParentObject = strings.TrimSpace(*object.SharingParentObject)
			}
			if object.SharingParentField != nil {
				projected.SharingParentField = strings.TrimSpace(*object.SharingParentField)
			}
		}
		if object.KeyPrefix != nil {
			projected.KeyPrefix = strings.TrimSpace(*object.KeyPrefix)
		}
		fieldNames := make(
			map[string]effectiveObjectSearchFieldIdentity,
			len(object.Fields),
		)
		compoundParents := make(map[string]string)
		if projectPresentationFacts {
			for _, parent := range object.Fields {
				if !parent.IsCompound {
					continue
				}
				for _, rawMember := range parent.ComposedFrom {
					member := strings.TrimSpace(rawMember)
					memberKey := strings.ToLower(member)
					if member == "" {
						return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
							"effective object-search metadata %q compound field %q contains a blank member",
							name, parent.APIName,
						)
					}
					if prior, duplicate := compoundParents[memberKey]; duplicate &&
						!strings.EqualFold(prior, parent.APIName) {
						return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
							"effective object-search metadata %q field %q belongs to compound fields %q and %q",
							name, member, prior, parent.APIName,
						)
					}
					compoundParents[memberKey] = strings.TrimSpace(parent.APIName)
				}
			}
		}
		for fieldIndex, field := range object.Fields {
			fieldName := strings.TrimSpace(field.APIName)
			fieldKey := strings.ToLower(fieldName)
			if fieldName == "" {
				return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
					"effective object-search metadata %q field[%d] has no API name",
					name, fieldIndex,
				)
			}
			if _, duplicate := fieldNames[fieldKey]; duplicate {
				return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
					"effective object-search metadata %q contains duplicate field %q",
					name, fieldName,
				)
			}
			fieldNames[fieldKey] = effectiveObjectSearchFieldIdentity{
				apiName: fieldName,
				typeID:  field.Type,
			}
			references := append([]string(nil), field.ReferenceTo...)
			sort.Strings(references)
			value := effectiveObjectSearchField{
				APIName:            fieldName,
				Label:              strings.TrimSpace(field.Label),
				Type:               string(field.Type),
				Required:           field.Required,
				DefaultedOnCreate:  field.DefaultedOnCreate,
				Createable:         field.Createable,
				Updateable:         field.Updateable,
				DefaultValue:       field.DefaultValue,
				IsNameField:        field.IsNameField,
				IsSystem:           field.IsSystem,
				ReferenceTo:        references,
				IsMasterDetail:     field.IsMasterDetail,
				PicklistDependency: field.PicklistDependency,
				Precision:          cloneOptionalInt(field.Precision),
				Scale:              cloneOptionalInt(field.Scale),
				Unique:             field.IsUnique,
			}
			if projectPresentationFacts {
				value.CompoundFieldName = compoundParents[fieldKey]
				if rolesByField := compoundRoles[key]; rolesByField != nil {
					value.CompoundComponentRole = strings.TrimSpace(rolesByField[fieldKey])
				}
				value.IsPolymorphic = field.IsPolymorphic
				value.InlineHelpText = cloneOptionalString(field.HelpText)
				value.MinValue = cloneOptionalFloat64(field.MinValue)
				value.MaxValue = cloneOptionalFloat64(field.MaxValue)
				value.MinLength = cloneOptionalInt(field.MinLength)
				value.MaxLength = cloneOptionalInt(field.MaxLength)
				if field.RelationshipName != nil {
					value.RelationshipName = strings.TrimSpace(*field.RelationshipName)
				}
			}
			if field.ChildRelationshipName != nil {
				value.ChildRelationshipName = strings.TrimSpace(
					*field.ChildRelationshipName,
				)
			}
			if field.DeleteRule != nil {
				value.DeleteRule = strings.TrimSpace(string(*field.DeleteRule))
			}
			if field.ControllingField != nil {
				value.ControllingField = strings.TrimSpace(*field.ControllingField)
			}
			for _, option := range field.Options {
				value.Options = append(value.Options, effectiveObjectSearchOption{
					Value: option.Value, Label: option.Label,
					Tags: append([]string(nil), option.Tags...),
				})
			}
			if field.ReturnType != nil {
				value.ReturnType = strings.TrimSpace(string(*field.ReturnType))
			}
			if field.Validator != nil {
				value.Validator = strings.TrimSpace(*field.Validator)
			}
			if field.ValidatorConfig != nil {
				value.ValidatorConfig = strings.TrimSpace(
					*field.ValidatorConfig,
				)
			}
			if projectFormulaReadFacts &&
				field.SiblingMaxParentField != nil {
				value.SiblingMaxParentField = strings.TrimSpace(*field.SiblingMaxParentField)
			}
			if projectFormulaReadFacts && effectiveFieldHasReadFormula(field) {
				formulaBody := *field.Formula
				value.Formula = &formulaBody
				value.PicklistValueSources = effectiveFormulaPicklistValueSources(
					objects, object, field,
				)
			}
			projected.Fields = append(projected.Fields, value)
		}
		if projectPathField && object.PathField != nil {
			pathField := strings.TrimSpace(*object.PathField)
			canonical, found := fieldNames[strings.ToLower(pathField)]
			if pathField == "" || !found {
				return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
					"effective object-search metadata %q path field %q is absent",
					name, pathField,
				)
			}
			if canonical.typeID != constants.FieldTypePicklist {
				return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
					"effective object-search metadata %q path field %q has type %q, want picklist",
					name, canonical.apiName, canonical.typeID,
				)
			}
			projected.PathField = canonical.apiName
		}
		if projectPresentationFacts && object.DisplayNameField != nil {
			displayNameField := *object.DisplayNameField
			projected.DisplayNameField = displayNameField
		}
		if projectListFields && object.ListFields != nil {
			listFields := make([]string, 0, len(object.ListFields))
			seenListFields := make(map[string]struct{}, len(object.ListFields))
			for fieldIndex, rawFieldName := range object.ListFields {
				fieldName := strings.TrimSpace(rawFieldName)
				fieldKey := strings.ToLower(fieldName)
				canonical, found := fieldNames[fieldKey]
				if fieldName == "" || !found {
					return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
						"effective object-search metadata %q list field[%d] %q is absent",
						name, fieldIndex, fieldName,
					)
				}
				if _, duplicate := seenListFields[fieldKey]; duplicate {
					return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
						"effective object-search metadata %q contains duplicate list field %q",
						name, canonical.apiName,
					)
				}
				seenListFields[fieldKey] = struct{}{}
				listFields = append(listFields, canonical.apiName)
			}
			projected.ListFields = &listFields
		}
		sort.Slice(projected.Fields, func(left, right int) bool {
			return projected.Fields[left].APIName <
				projected.Fields[right].APIName
		})
		for _, field := range projected.SearchAllDefaultFields {
			if _, found := fieldNames[strings.ToLower(field)]; !found {
				return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
					"effective search-all declaration %q references absent field %q",
					name, field,
				)
			}
		}
		document.Objects = append(document.Objects, projected)
		delete(defaults, key)
	}
	if len(defaults) != 0 {
		var names []string
		for name := range defaults {
			names = append(names, name)
		}
		sort.Strings(names)
		return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf(
			"effective search-all declaration references absent object %q",
			names[0],
		)
	}
	sort.Slice(document.Objects, func(left, right int) bool {
		return document.Objects[left].APIName < document.Objects[right].APIName
	})
	encoded, err := json.Marshal(document)
	if err != nil {
		return catalogapp.EffectiveMetadataComponent{}, err
	}
	return catalogapp.EffectiveMetadataComponent{
		ComponentKind:          consumerv1.EffectiveObjectSearchComponentKind,
		ComponentFormatVersion: componentFormatVersion,
		BusinessKey:            consumerv1.EffectiveObjectSearchComponentBusinessKey,
		ContentDigest:          consumerv1.ComputeEffectiveMetadataComponentDigest(encoded),
		CanonicalBehavior:      encoded,
	}, nil
}

func effectiveFieldHasReadFormula(field models.FieldMetadata) bool {
	if field.Formula == nil || strings.TrimSpace(*field.Formula) == "" {
		return false
	}
	if field.Type == constants.FieldTypeFormula {
		return true
	}
	return field.FormulaMode != nil && *field.FormulaMode == "active"
}

func effectiveFormulaPicklistValueSources(
	objects []*models.ObjectMetadata,
	current *models.ObjectMetadata,
	formulaField models.FieldMetadata,
) []effectiveObjectSearchFieldSource {
	if current == nil || !effectiveFieldHasReadFormula(formulaField) {
		return nil
	}
	root, err := formula.ParseNormalizedExpressionAST(*formulaField.Formula)
	if err != nil {
		return nil
	}
	call, ok := root.(*ast.CallNode)
	if !ok || len(call.Arguments) != 1 {
		return nil
	}
	callee, ok := call.Callee.(*ast.IdentifierNode)
	if !ok || !strings.EqualFold(callee.Value, "TEXT") {
		return nil
	}
	sourceObject, sourceField, ok := resolveEffectiveFormulaPicklistSource(
		objects, current, call.Arguments[0],
	)
	if !ok {
		return nil
	}
	return []effectiveObjectSearchFieldSource{{
		Object: sourceObject.APIName,
		Field:  sourceField.APIName,
	}}
}

func resolveEffectiveFormulaPicklistSource(
	objects []*models.ObjectMetadata,
	current *models.ObjectMetadata,
	node ast.Node,
) (*models.ObjectMetadata, *models.FieldMetadata, bool) {
	root, segments, ok := effectiveFormulaMemberChain(node)
	if !ok {
		return nil, nil, false
	}
	if strings.EqualFold(root, "__Record") {
		if len(segments) == 0 {
			return nil, nil, false
		}
		root = segments[0]
		segments = segments[1:]
	}
	if len(segments) == 0 {
		if strings.HasPrefix(root, "__") {
			return nil, nil, false
		}
		field, found := effectiveFormulaField(current, root)
		if !found || field.Type != constants.FieldTypePicklist {
			return nil, nil, false
		}
		return current, field, true
	}
	if len(segments) != 1 {
		return nil, nil, false
	}
	var targetName string
	for index := range current.Fields {
		candidate := &current.Fields[index]
		if candidate.RelationshipName == nil ||
			!strings.EqualFold(strings.TrimSpace(*candidate.RelationshipName), root) {
			continue
		}
		if !constants.IsReferenceType(candidate.Type) || candidate.IsPolymorphic ||
			len(candidate.ReferenceTo) != 1 || targetName != "" {
			return nil, nil, false
		}
		targetName = strings.TrimSpace(candidate.ReferenceTo[0])
	}
	if targetName == "" {
		return nil, nil, false
	}
	target, found := effectiveFormulaObject(objects, targetName)
	if !found {
		return nil, nil, false
	}
	field, found := effectiveFormulaField(target, segments[0])
	if !found || field.Type != constants.FieldTypePicklist {
		return nil, nil, false
	}
	return target, field, true
}

func effectiveFormulaMemberChain(node ast.Node) (string, []string, bool) {
	switch value := node.(type) {
	case *ast.ChainNode:
		return effectiveFormulaMemberChain(value.Node)
	case *ast.IdentifierNode:
		return value.Value, nil, value.Value != ""
	case *ast.MemberNode:
		root, segments, ok := effectiveFormulaMemberChain(value.Node)
		if !ok {
			return "", nil, false
		}
		var segment string
		switch property := value.Property.(type) {
		case *ast.StringNode:
			segment = property.Value
		case *ast.IdentifierNode:
			segment = property.Value
		default:
			return "", nil, false
		}
		if segment == "" {
			return "", nil, false
		}
		return root, append(segments, segment), true
	default:
		return "", nil, false
	}
}

func effectiveFormulaObject(
	objects []*models.ObjectMetadata,
	name string,
) (*models.ObjectMetadata, bool) {
	var result *models.ObjectMetadata
	for _, object := range objects {
		if object == nil || !strings.EqualFold(strings.TrimSpace(object.APIName), name) {
			continue
		}
		if result != nil {
			return nil, false
		}
		result = object
	}
	return result, result != nil
}

func effectiveFormulaField(
	object *models.ObjectMetadata,
	name string,
) (*models.FieldMetadata, bool) {
	if object == nil {
		return nil, false
	}
	var result *models.FieldMetadata
	for index := range object.Fields {
		field := &object.Fields[index]
		if !strings.EqualFold(strings.TrimSpace(field.APIName), name) {
			continue
		}
		if result != nil {
			return nil, false
		}
		result = field
	}
	return result, result != nil
}

func cloneOptionalInt(value *int) *int {
	if value == nil {
		return nil
	}
	cloned := *value
	return &cloned
}

func validateEffectiveDisplayNameFields(objects []*models.ObjectMetadata) error {
	specs := make([]packs.ObjectSpec, 0, len(objects))
	for index, object := range objects {
		if object == nil {
			return fmt.Errorf("effective object-search metadata[%d] is nil", index)
		}
		spec := packs.ObjectSpec{APIName: object.APIName}
		if object.DisplayNameField != nil {
			spec.DisplayNameField = *object.DisplayNameField
		}
		spec.Fields = make([]packs.FieldSpec, 0, len(object.Fields))
		for _, field := range object.Fields {
			relationshipName := ""
			if field.RelationshipName != nil {
				relationshipName = *field.RelationshipName
			}
			spec.Fields = append(spec.Fields, packs.FieldSpec{
				APIName:          field.APIName,
				Type:             string(field.Type),
				ReferenceTo:      append([]string(nil), field.ReferenceTo...),
				RelationshipName: relationshipName,
				IsPolymorphic:    field.IsPolymorphic,
			})
		}
		specs = append(specs, spec)
	}
	if err := packs.ValidateSpecDisplayNameFields(specs); err != nil {
		return fmt.Errorf("effective object-search display-name metadata: %w", err)
	}
	return nil
}

func validEffectiveMetadataIdentifier(value string) bool {
	if value == "" {
		return false
	}
	for _, character := range value {
		if (character >= 'a' && character <= 'z') ||
			(character >= 'A' && character <= 'Z') ||
			(character >= '0' && character <= '9') || character == '_' {
			continue
		}
		return false
	}
	return true
}

func cloneOptionalString(value *string) *string {
	if value == nil {
		return nil
	}
	cloned := *value
	return &cloned
}

func cloneOptionalFloat64(value *float64) *float64 {
	if value == nil {
		return nil
	}
	cloned := *value
	return &cloned
}

func (r *RepositoryMetadataReader) GetRuntimeSearchAllDefaultFields(
	ctx context.Context,
) ([]searchAllDefaultFieldsDeclaration, error) {
	values, err := controlplane.ReadActiveRuntimeSearchAllDefaultFields(
		ctx,
		r.GetExecutor(ctx),
	)
	if err != nil {
		return nil, err
	}
	result := make([]searchAllDefaultFieldsDeclaration, 0, len(values))
	for _, value := range values {
		result = append(result, searchAllDefaultFieldsDeclaration{
			ObjectAPIName: value.ObjectAPIName,
			Fields:        append([]string(nil), value.Fields...),
		})
	}
	return result, nil
}

var _ EffectiveObjectSearchMetadataReader = (*RepositoryMetadataReader)(nil)
