package sfcrmappservice

import (
	"context"
	"encoding/base64"
	"fmt"
	historysemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/queryv1"
	"net/http"
	"sort"
	"strconv"
	"strings"

	"github.com/pingcap-inc/nexuscrm-app-packs/sfcrm/querycodec"
	crmwire "github.com/pingcap-inc/nexuscrm-app-packs/sfcrm/wire"
	permissionsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/effectivepermissionsv1"
)

type objectDescribeRoute struct {
	version  string
	objectID string
	global   bool
}

func matchObjectDescribeRoute(path string) (objectDescribeRoute, bool) {
	parts := strings.Split(strings.Trim(path, "/"), "/")
	if len(parts) == 4 && parts[0] == "services" && parts[1] == "data" &&
		parts[3] == "sobjects" {
		if _, supported := recordViewVersions[parts[2]]; !supported {
			return objectDescribeRoute{}, false
		}
		return objectDescribeRoute{version: parts[2], global: true}, true
	}
	if len(parts) != 6 || parts[0] != "services" || parts[1] != "data" ||
		parts[3] != "sobjects" || parts[5] != "describe" ||
		!validSearchIdentifier(parts[4]) {
		return objectDescribeRoute{}, false
	}
	if _, supported := recordViewVersions[parts[2]]; !supported {
		return objectDescribeRoute{}, false
	}
	return objectDescribeRoute{version: parts[2], objectID: parts[4]}, true
}

func describeGlobalObjectProjection(
	version string,
	spec searchObjectSpec,
	permission permissionsemantic.ObjectPermission,
	permissions permissionsemantic.Response,
) map[string]any {
	searchable := spec.Searchable == nil || *spec.Searchable
	pluralLabel := spec.PluralLabel
	if pluralLabel == "" {
		pluralLabel = spec.Label
	}
	tableType := ""
	if spec.TableType != nil {
		tableType = *spec.TableType
	}
	isSystem := strings.HasPrefix(spec.APIName, "_System_")
	sobjectsBase := "/services/data/" + version + "/sobjects/" + spec.APIName
	result := map[string]any{
		"activateable":          false,
		"associateEntityType":   nil,
		"associateParentEntity": nil,
		"createable":            permission.CanCreate,
		"custom":                describeObjectIsCustom(spec),
		"customSetting":         false,
		"deletable":             permission.CanDelete,
		"deprecatedAndHidden":   false,
		"feedEnabled":           true,
		"hasSubtypes":           false,
		"isSubtype":             false,
		"keyPrefix":             spec.KeyPrefix,
		"label":                 spec.Label,
		"labelPlural":           pluralLabel,
		"layoutable":            !isSystem,
		"mergeable":             false,
		"mruEnabled":            true,
		"name":                  spec.APIName,
		"isSystem":              isSystem,
		"queryable":             true,
		"replicateable":         true,
		"retrieveable":          true,
		"searchable":            searchable,
		"tableType":             tableType,
		"triggerable":           !isSystem,
		"undeletable":           true,
		"updateable":            permission.CanEdit,
		"urls": map[string]string{
			"sobject":     sobjectsBase,
			"describe":    sobjectsBase + "/describe",
			"rowTemplate": sobjectsBase + "/{ID}",
		},
	}
	if spec.PresentationFactsV5 {
		result["sharingModel"] = spec.SharingModel
		if spec.SharingModel == "ControlledByParent" && spec.SharingParentObject != "" {
			if _, readable := objectPermissionForDescribe(permissions, spec.SharingParentObject); readable {
				result["sharingParentObject"] = spec.SharingParentObject
			}
		}
	}
	return result
}

func historyParentNameSupportsDescribe(name string) bool {
	return !querycodec.IsHistoryObject(name) && name != querycodec.OpportunityHistoryObject && querycodec.SupportsFieldHistory(name)
}

func historySchemaSupportsDescribe(spec searchObjectSpec) bool {
	if !describeAuthorityIsCurrent(spec) || !historyParentNameSupportsDescribe(spec.APIName) {
		return false
	}
	for _, field := range spec.Fields {
		if strings.TrimSpace(field.APIName) != "" {
			return true
		}
	}
	return false
}

func describeGlobalHistoryProjection(version string, parent searchObjectSpec) map[string]any {
	name := querycodec.HistoryObjectName(parent.APIName)
	label := parent.Label + " History"
	if name == querycodec.OpportunityFieldHistoryObject {
		label = parent.Label + " Field History"
	}
	base := "/services/data/" + version + "/sobjects/" + name
	return map[string]any{
		"activateable": false, "associateEntityType": nil, "associateParentEntity": nil,
		"createable": false, "custom": describeObjectIsCustom(parent), "customSetting": false,
		"deletable": false, "deprecatedAndHidden": false, "feedEnabled": false,
		"hasSubtypes": false, "isSubtype": false, "keyPrefix": "", "label": label,
		"labelPlural": label, "layoutable": false, "mergeable": false, "mruEnabled": false,
		"name": name, "isSystem": true, "queryable": true, "replicateable": true,
		"retrieveable": false, "searchable": false, "tableType": "", "triggerable": false,
		"undeletable": false, "updateable": false,
		"urls": map[string]string{
			"sobject": base, "describe": base + "/describe", "rowTemplate": base + "/{ID}",
		},
	}
}

func historyDescribeField(
	name string,
	label string,
	fieldType string,
	referenceTo []string,
	readable bool,
	filterable bool,
	sortable bool,
	picklistValues []map[string]any,
) map[string]any {
	soapType := "xsd:string"
	switch fieldType {
	case "id", "reference":
		soapType = "tns:ID"
	case "datetime":
		soapType = "xsd:dateTime"
	case "anyType":
		soapType = "xsd:anyType"
	}
	if referenceTo == nil {
		referenceTo = []string{}
	}
	if picklistValues == nil {
		picklistValues = []map[string]any{}
	}
	return map[string]any{
		"aggregatable": false, "autoNumber": false, "byteLength": 0,
		"calculated": false, "calculatedFormula": nil, "cascadeDelete": false,
		"caseSensitive": false, "compoundFieldName": nil, "controllerName": nil,
		"createable": false, "custom": false, "defaultValue": nil,
		"defaultValueFormula": nil, "defaultedOnCreate": false, "dependentPicklist": false,
		"deprecatedAndHidden": false, "digits": 0, "displayLocationInDecimal": false,
		"encrypted": false, "externalId": false, "extraTypeInfo": nil,
		"filterable": filterable, "filteredLookupInfo": nil, "formulaTreatNullNumberAsZero": false,
		"groupable": false, "highScaleNumber": false, "htmlFormatted": false,
		"idLookup": name == "Id", "inlineHelpText": nil, "label": label,
		"length": 0, "mask": nil, "maskType": nil, "name": name,
		"nameField": false, "namePointing": false,
		"nillable":       name != "Id" && !strings.HasSuffix(name, "Id"),
		"permissionable": false, "picklistValues": picklistValues,
		"polymorphicForeignKey": false, "precision": 0, "queryByDistance": false,
		"referenceTargetField": nil, "referenceTo": referenceTo, "relationshipName": nil,
		"relationshipOrder": nil, "restrictedDelete": false, "restrictedPicklist": false,
		"scale": 0, "searchPrefilterable": true, "soapType": soapType,
		"sortable": sortable, "type": fieldType, "unique": false, "updateable": false,
		"writeRequiresMasterRead": false, "readable": readable,
	}
}

// virtualHistoryParent resolves the same derived schema used by Describe. Physical
// Catalog objects retain precedence; suffix matching alone never grants authority.
func virtualHistoryParent(objectName string, specs map[string]searchObjectSpec) (searchObjectSpec, bool) {
	if _, physical := specs[strings.ToLower(objectName)]; physical || !querycodec.IsHistoryObject(objectName) {
		return searchObjectSpec{}, false
	}
	parent, found := specs[strings.ToLower(querycodec.ParentObjectFromHistoryName(objectName))]
	return parent, found && historySchemaSupportsDescribe(parent) && querycodec.HistoryObjectName(parent.APIName) == objectName
}

func historyObjectFields(historyObjectName string, parent searchObjectSpec, permissions permissionsemantic.Response) []map[string]any {
	fieldPermissions := fieldPermissionsForDescribe(permissions, parent.APIName)
	readableFields := make([]string, 0, len(parent.Fields))
	for _, field := range parent.Fields {
		if permission, ok := fieldPermissions[strings.ToLower(field.APIName)]; ok && permission.CanRead {
			readableFields = append(readableFields, field.APIName)
		}
	}
	picklistValues := make([]map[string]any, 0, len(readableFields))
	for _, fieldName := range readableFields {
		picklistValues = append(picklistValues, map[string]any{
			"active": true, "defaultValue": false, "label": fieldName, "value": fieldName,
		})
	}

	result := make([]map[string]any, 0, 8)
	for _, field := range historyColumns(historyObjectName, parent) {
		readable := true
		var values []map[string]any
		switch field.source {
		case historysemantic.HistoryColumnOldValue, historysemantic.HistoryColumnNewValue:
			readable = len(readableFields) != 0
		case historysemantic.HistoryColumnField:
			values = picklistValues
		}
		result = append(result, historyDescribeField(field.name, field.label, field.fieldType, field.referenceTo, readable, field.filterable, field.sortable, values))
	}
	return result
}

func describeHistoryObjectProjection(
	version string,
	historyObjectName string,
	parent searchObjectSpec,
	permissions permissionsemantic.Response,
) map[string]any {
	label := parent.Label + " History"
	if historyObjectName == querycodec.OpportunityFieldHistoryObject {
		label = parent.Label + " Field History"
	}
	fields := historyObjectFields(historyObjectName, parent, permissions)
	base := fmt.Sprintf("/services/data/%s/sobjects/%s", version, historyObjectName)
	return map[string]any{
		"actionOverrides": []any{}, "associateEntityType": nil, "associateParentEntity": nil,
		"childRelationships": []any{}, "createable": false, "custom": describeObjectIsCustom(parent),
		"deletable": false, "deprecatedAndHidden": false, "feedEnabled": false,
		"fields": fields, "label": label, "labelPlural": label, "layoutable": false,
		"name": historyObjectName, "namedLayoutInfos": []any{}, "queryable": true,
		"recordTypeInfos": []any{}, "replicateable": true, "retrieveable": false,
		"searchable": false, "supportedScopes": []any{}, "sobjectDescribeOption": "FULL",
		"triggerable": false, "undeletable": false, "updateable": false,
		"urls": map[string]string{
			"sobject": base, "describe": base + "/describe", "rowTemplate": base + "/{ID}",
		},
	}
}

func (service *Service) readGlobalDescribe(
	ctx context.Context,
	bearer string,
	version string,
) (map[string]any, error) {
	view, specs, err := readObjectSpecs(ctx, service.appMetadataV3)
	if err != nil {
		return nil, err
	}
	names, err := permissionResourceTypes(specs)
	if err != nil {
		return nil, err
	}
	revision := view.Receipts.CatalogRevision
	aggregate, err := readEffectivePermissionSelection(
		ctx, service.permissionMetadata.readEffective, bearer, "", revision,
		[]permissionsemantic.Section{permissionsemantic.SectionObjectPermissions},
		names,
	)
	if err != nil {
		return nil, err
	}
	permissions := aggregate.response()
	if err := validateSearchMetadataAuthority(
		ctx, service.reconcileAppMetadataV3, view, permissions.Receipts,
	); err != nil {
		return nil, err
	}
	objects := make([]map[string]any, 0, len(names)*2)
	for _, name := range names {
		spec := specs[strings.ToLower(name)]
		permission, readable := objectPermissionForDescribe(permissions, spec.APIName)
		if !readable {
			continue
		}
		objects = append(objects, describeGlobalObjectProjection(version, spec, permission, permissions))
		if historySchemaSupportsDescribe(spec) {
			objects = append(objects, describeGlobalHistoryProjection(version, spec))
		}
	}
	return map[string]any{
		"encoding":     "UTF-8",
		"maxBatchSize": 200,
		"sobjects":     objects,
	}, nil
}

func objectPermissionForDescribe(
	permissions permissionsemantic.Response,
	objectID string,
) (permissionsemantic.ObjectPermission, bool) {
	for _, permission := range permissions.ObjectPermissions {
		if strings.EqualFold(permission.ResourceType, objectID) {
			return permission, permission.CanRead
		}
	}
	return permissionsemantic.ObjectPermission{}, false
}

func fieldPermissionsForDescribe(
	permissions permissionsemantic.Response,
	objectID string,
) map[string]permissionsemantic.FieldPermission {
	result := make(map[string]permissionsemantic.FieldPermission)
	for _, permission := range permissions.FieldPermissions {
		if strings.EqualFold(permission.ResourceType, objectID) {
			result[strings.ToLower(unqualifiedPermissionField(permission.FieldName))] = permission
		}
	}
	return result
}

func describeRuntimePicklistInfo(
	field searchFieldSpec,
	referenceTo []string,
	specs map[string]searchObjectSpec,
	permissions permissionsemantic.Response,
) (map[string]any, bool) {
	if !strings.EqualFold(strings.TrimSpace(field.Validator), runtimeScopedPicklistRule) {
		return nil, false
	}
	// Keep the runtime marker present even when malformed metadata or effective
	// permissions make its descriptor unusable. The CRM frontend treats an
	// empty runtimePicklist descriptor as unresolvable and fails closed instead
	// of silently offering authored fallback options that Runtime will reject.
	unusable := func() (map[string]any, bool) {
		return map[string]any{}, true
	}
	fieldType := describeFieldType(field)
	if (fieldType != "picklist" && fieldType != "multipicklist") ||
		strings.TrimSpace(field.ControllingField) == "" ||
		len(field.ReferenceTo) != 1 || len(referenceTo) != 1 || specs == nil {
		return unusable()
	}

	sourceObject := strings.TrimSpace(field.ReferenceTo[0])
	if sourceObject == "" || !strings.EqualFold(sourceObject, referenceTo[0]) {
		return unusable()
	}
	source, found := specs[strings.ToLower(sourceObject)]
	if !found {
		return unusable()
	}
	sourcePermissions := fieldPermissionsForDescribe(permissions, source.APIName)
	readableSourceField := func(fieldName string) (searchFieldSpec, bool) {
		sourceField, exists := layoutFieldSpec(source, fieldName)
		permission, readable := sourcePermissions[strings.ToLower(fieldName)]
		return sourceField, exists && readable && permission.CanRead
	}

	controllerName := strings.TrimSpace(field.ControllingField)
	if _, readable := readableSourceField(controllerName); !readable {
		return unusable()
	}
	labelField := ""
	if label, readable := readableSourceField("Label"); readable {
		labelField = label.APIName
	} else {
		for _, candidate := range source.Fields {
			if candidate.IsNameField {
				if name, readable := readableSourceField(candidate.APIName); readable {
					labelField = name.APIName
					break
				}
			}
		}
		if labelField == "" {
			if name, readable := readableSourceField("Name"); readable {
				labelField = name.APIName
			}
		}
	}
	if labelField == "" {
		return unusable()
	}
	sortField := labelField
	if sortOrder, readable := readableSourceField("SortOrder"); readable {
		sortField = sortOrder.APIName
	}

	return map[string]any{
		"sourceObject": source.APIName,
		"valueField":   labelField,
		"labelField":   labelField,
		"filterMappings": []map[string]any{{
			"sourceField": controllerName,
			"recordField": controllerName,
		}},
		"sortField": sortField,
		"sortOrder": "ASC",
	}, true
}

func describeObjectProjection(
	version string,
	spec searchObjectSpec,
	objectPermission permissionsemantic.ObjectPermission,
	permissions permissionsemantic.Response,
	recordTypes recordTypeProjection,
	orderedListFields []string,
	childRelationships []map[string]any,
) map[string]any {
	return describeObjectProjectionWithSpecs(
		version, spec, objectPermission, permissions, recordTypes,
		orderedListFields, childRelationships, nil,
	)
}

func describeObjectProjectionWithSpecs(
	version string,
	spec searchObjectSpec,
	objectPermission permissionsemantic.ObjectPermission,
	permissions permissionsemantic.Response,
	recordTypes recordTypeProjection,
	orderedListFields []string,
	childRelationships []map[string]any,
	specs map[string]searchObjectSpec,
) map[string]any {
	if childRelationships == nil {
		childRelationships = []map[string]any{}
	}
	fieldPermissions := fieldPermissionsForDescribe(permissions, spec.APIName)
	fields := make([]map[string]any, 0, len(spec.Fields))
	for _, field := range spec.Fields {
		permission, ok := fieldPermissions[strings.ToLower(field.APIName)]
		if !ok || !permission.CanRead {
			continue
		}
		fieldType := describeFieldType(field)
		calculated := describeFieldIsCalculated(field)
		var calculatedFormula any
		if calculated && field.Formula != nil {
			calculatedFormula = *field.Formula
		}
		var compoundFieldName any
		var compoundComponentRole any
		if value := strings.TrimSpace(field.CompoundFieldName); value != "" {
			if compound, found := fieldPermissions[strings.ToLower(value)]; found && compound.CanRead {
				if _, exists := layoutFieldSpec(spec, value); exists {
					compoundFieldName = value
					if role := strings.TrimSpace(field.CompoundComponentRole); role != "" {
						compoundComponentRole = role
					}
				}
			}
		}
		var controllerName any
		if value := strings.TrimSpace(field.ControllingField); value != "" {
			if controller, found := fieldPermissions[strings.ToLower(value)]; found && controller.CanRead {
				if _, exists := layoutFieldSpec(spec, value); exists {
					controllerName = value
				}
			}
		}
		referenceTo := make([]string, 0, len(field.ReferenceTo))
		for _, target := range field.ReferenceTo {
			if _, readable := objectPermissionForDescribe(permissions, target); readable {
				referenceTo = append(referenceTo, target)
			}
		}
		authorizedField := field
		if controllerName == nil {
			authorizedField.ControllingField = ""
		}
		runtimePicklist, runtimeScopedPicklist := describeRuntimePicklistInfo(
			authorizedField, referenceTo, specs, permissions,
		)
		runtimeLookup := describeRuntimeLookupInfo(
			authorizedField, referenceTo, spec, specs, permissions,
		)
		cascadeDelete, restrictedDelete, deleteSemanticsKnown :=
			describeRelationshipDeleteSemantics(field)
		if len(referenceTo) == 0 {
			cascadeDelete = false
			restrictedDelete = false
			deleteSemanticsKnown = true
		}
		if !deleteSemanticsKnown {
			cascadeDelete = false
			restrictedDelete = false
		}
		var relationshipName any
		if field.RelationshipName != "" && len(referenceTo) != 0 {
			relationshipName = field.RelationshipName
		}
		length := describeFieldLength(field, fieldType)
		projected := map[string]any{
			"name":                  field.APIName,
			"label":                 field.Label,
			"type":                  fieldType,
			"unique":                field.Unique,
			"externalId":            field.Unique,
			"idLookup":              field.Unique || field.APIName == "Id",
			"readable":              true,
			"createable":            objectPermission.CanCreate && permission.CanCreate && field.Createable,
			"updateable":            objectPermission.CanEdit && permission.CanEdit && field.Updateable,
			"nillable":              fieldType != "boolean" && !field.Required,
			"defaultedOnCreate":     field.DefaultedOnCreate || field.DefaultValue != nil,
			"defaultValue":          describeDefaultValue(field, fieldType),
			"nameField":             field.IsNameField,
			"calculated":            calculated,
			"calculatedFormula":     calculatedFormula,
			"custom":                describeFieldIsCustom(field),
			"htmlFormatted":         describeFieldIsHTMLFormatted(field),
			"autoNumber":            describeFieldIsAutoNumber(field),
			"compoundFieldName":     compoundFieldName,
			"compoundComponentRole": compoundComponentRole,
			"inlineHelpText":        field.InlineHelpText,
			"length":                length,
			"byteLength":            length,
			"polymorphicForeignKey": field.IsPolymorphic && len(referenceTo) > 1,
			"relationshipName":      relationshipName,
			"cascadeDelete":         cascadeDelete,
			"restrictedDelete":      restrictedDelete,
			"controllerName":        controllerName,
			"dependentPicklist": controllerName != nil &&
				(len(field.PicklistDependency) != 0 || runtimeScopedPicklist),
			"referenceTo": referenceTo,
			"picklistValues": describeAuthorizedPicklistValues(
				spec, authorizedField, specs, permissions,
			),
		}
		if runtimeScopedPicklist || runtimeLookup != nil {
			filtered := map[string]any{}
			if runtimeScopedPicklist {
				filtered["runtimePicklist"] = runtimePicklist
			}
			if runtimeLookup != nil {
				filtered["runtimeLookup"] = runtimeLookup
			}
			projected["filteredLookupInfo"] = filtered
		}
		// Catalog owns authored/resolved numeric shape. L1 only projects those
		// immutable facts into the Salesforce describe wire. Integer is the one
		// shape whose neutral type itself proves the Salesforce default.
		if field.Precision != nil && field.Scale != nil {
			projected["precision"] = *field.Precision
			projected["scale"] = *field.Scale
		} else if fieldType == "int" {
			projected["precision"] = 18
			projected["scale"] = 0
		}
		fields = append(fields, projected)
	}
	searchable := spec.Searchable == nil || *spec.Searchable
	pluralLabel := spec.PluralLabel
	if pluralLabel == "" {
		pluralLabel = spec.Label
	}
	sobjectsBase := "/services/data/" + version + "/sobjects/" + spec.APIName
	recordTypeInfos := make([]map[string]any, 0, len(recordTypes.entries))
	for _, entry := range recordTypes.entries {
		recordTypeInfos = append(recordTypeInfos, recordTypeInfo(version, spec.APIName, entry))
	}
	response := map[string]any{
		"name":                spec.APIName,
		"label":               spec.Label,
		"labelPlural":         pluralLabel,
		"keyPrefix":           spec.KeyPrefix,
		"custom":              describeObjectIsCustom(spec),
		"deprecatedAndHidden": false,
		"feedEnabled":         true,
		"queryable":           true,
		"retrieveable":        true,
		"replicateable":       true,
		"searchable":          searchable,
		"triggerable":         !strings.HasPrefix(spec.APIName, "_System_"),
		"mergeable":           false,
		"createable":          objectPermission.CanCreate,
		"updateable":          objectPermission.CanEdit,
		"deletable":           objectPermission.CanDelete,
		"undeletable":         true,
		"layoutable":          true,
		"recordTypeInfos":     recordTypeInfos,
		"childRelationships":  childRelationships,
		"fields":              fields,
		"urls": map[string]string{
			"approvalLayouts": sobjectsBase + "/describe/approvalLayouts",
			"compactLayouts":  sobjectsBase + "/describe/compactLayouts",
			"defaultValues":   sobjectsBase + "/defaultValues",
			"describe":        sobjectsBase + "/describe",
			"layouts":         sobjectsBase + "/describe/layouts",
			"listviews":       sobjectsBase + "/listviews",
			"quickActions":    sobjectsBase + "/quickActions",
			"rowTemplate":     sobjectsBase + "/{ID}",
			"sobject":         sobjectsBase,
		},
	}
	if orderedListFields != nil {
		response["listFields"] = readableObjectFieldNames(
			spec, fieldPermissions, orderedListFields,
		)
	}
	if spec.PathField != "" {
		if permission, ok := fieldPermissions[strings.ToLower(spec.PathField)]; ok && permission.CanRead {
			response["pathField"] = spec.PathField
		}
	}
	if spec.PresentationFactsV5 && spec.DisplayNameField != "" {
		if readableSearchDisplayNameField(spec, permissions) {
			response["displayNameField"] = spec.DisplayNameField
		}
	}
	return response
}

func describeChildRelationships(
	parent searchObjectSpec,
	specs map[string]searchObjectSpec,
	permissions permissionsemantic.Response,
) ([]map[string]any, error) {
	relationships := make([]map[string]any, 0)
	seenNames := make(map[string]struct{})
	for _, child := range specs {
		if _, readable := objectPermissionForDescribe(permissions, child.APIName); !readable {
			continue
		}
		fieldPermissions := fieldPermissionsForDescribe(permissions, child.APIName)
		for _, field := range child.Fields {
			name := strings.TrimSpace(field.ChildRelationshipName)
			if name == "" {
				continue
			}
			referencesParent := false
			for _, target := range field.ReferenceTo {
				if strings.EqualFold(target, parent.APIName) {
					referencesParent = true
					break
				}
			}
			if !referencesParent {
				continue
			}
			if !describeAuthorityIsCurrent(child) || !validSearchIdentifier(name) {
				return nil, unavailableSearch()
			}
			permission, readable := fieldPermissions[strings.ToLower(field.APIName)]
			if !readable || !permission.CanRead {
				continue
			}
			key := strings.ToLower(name)
			if _, duplicate := seenNames[key]; duplicate {
				return nil, unavailableSearch()
			}
			seenNames[key] = struct{}{}
			cascadeDelete, restrictedDelete, ok := describeRelationshipDeleteSemantics(field)
			if !ok {
				return nil, unavailableSearch()
			}
			relationships = append(relationships, map[string]any{
				"cascadeDelete":       cascadeDelete,
				"childSObject":        child.APIName,
				"deprecatedAndHidden": false,
				"field":               field.APIName,
				"junctionIdListNames": []string{},
				"junctionReferenceTo": []string{},
				"relationshipName":    name,
				"restrictedDelete":    restrictedDelete,
			})
		}
	}
	sort.Slice(relationships, func(left, right int) bool {
		leftKey := relationships[left]["relationshipName"].(string) + "\x00" +
			relationships[left]["childSObject"].(string) + "\x00" +
			relationships[left]["field"].(string)
		rightKey := relationships[right]["relationshipName"].(string) + "\x00" +
			relationships[right]["childSObject"].(string) + "\x00" +
			relationships[right]["field"].(string)
		return leftKey < rightKey
	})
	return relationships, nil
}

// objectDescribePermissionSelection returns exactly the resource authorities
// needed to project one DescribeSObjectResult. Outgoing references control
// referenceTo disclosure; inbound named references control childRelationships.
// Keeping this assembly in L1 preserves the neutral L0 permission engine and
// avoids asking Runtime for every field permission in the application.
func objectDescribePermissionSelection(
	spec searchObjectSpec,
	specs map[string]searchObjectSpec,
) (*permissionsemantic.Selection, error) {
	resources := []string{spec.APIName}
	for _, field := range spec.Fields {
		for _, referenced := range field.ReferenceTo {
			target, found := specs[strings.ToLower(referenced)]
			if found && describeAuthorityIsCurrent(target) {
				resources = append(resources, target.APIName)
			}
		}
		for _, source := range field.PicklistValueSources {
			target, found := specs[strings.ToLower(source.Object)]
			if found && describeAuthorityIsCurrent(target) {
				resources = append(resources, target.APIName)
			}
		}
	}
	for _, child := range specs {
		if !describeAuthorityIsCurrent(child) {
			continue
		}
		for _, field := range child.Fields {
			if strings.TrimSpace(field.ChildRelationshipName) == "" {
				continue
			}
			for _, referenced := range field.ReferenceTo {
				if strings.EqualFold(referenced, spec.APIName) {
					resources = append(resources, child.APIName)
					break
				}
			}
		}
	}
	return boundedRecordUIPermissionSelection(resources)
}

func describeRelationshipDeleteSemantics(field searchFieldSpec) (bool, bool, bool) {
	if field.IsMasterDetail {
		return true, false, true
	}
	rule := strings.ToLower(strings.NewReplacer("_", "", "-", "", " ", "").Replace(
		strings.TrimSpace(field.DeleteRule),
	))
	switch rule {
	case "", "restrict", "noaction":
		return false, true, true
	case "cascade":
		return true, false, true
	case "setnull":
		return false, false, true
	default:
		return false, false, false
	}
}

func describeObjectIsCustom(object searchObjectSpec) bool {
	if object.TableType == nil {
		return false
	}
	return strings.EqualFold(strings.TrimSpace(*object.TableType), "custom_object")
}

func describeFieldIsCustom(field searchFieldSpec) bool {
	if field.IsSystem == nil {
		// The effective object-search component is sparse: false is omitted.
		// A present true value identifies a Runtime-owned system field.
		return true
	}
	return !*field.IsSystem
}

func describeFieldIsHTMLFormatted(field searchFieldSpec) bool {
	switch strings.ToLower(strings.TrimSpace(field.Type)) {
	case "rich_text", "richtextarea":
		return true
	default:
		return false
	}
}

func describeFieldIsAutoNumber(field searchFieldSpec) bool {
	return strings.EqualFold(strings.TrimSpace(field.Type), "autonumber")
}

func describeFieldIsCalculated(field searchFieldSpec) bool {
	if field.Formula != nil && strings.TrimSpace(*field.Formula) != "" {
		return true
	}
	switch strings.ToLower(strings.TrimSpace(field.Type)) {
	case "formula", "rollupsummary":
		return true
	default:
		return false
	}
}

func describeFieldType(field searchFieldSpec) string {
	if field.APIName == "Id" {
		return "id"
	}
	value := strings.ToLower(strings.TrimSpace(field.Type))
	if (value == "formula" || value == "rollupsummary") && strings.TrimSpace(field.ReturnType) != "" {
		value = strings.ToLower(strings.TrimSpace(field.ReturnType))
	}
	if strings.EqualFold(strings.TrimSpace(field.Validator), runtimeScopedPicklistRule) {
		switch value {
		case "text", "short_text", "string", "select", "picklist":
			return "picklist"
		case "multi_select", "multipicklist":
			return "multipicklist"
		}
	}
	switch value {
	case "text", "short_text", "string", "autonumber":
		return "string"
	case "long_text", "rich_text", "textarea", "richtextarea":
		return "textarea"
	case "number", "double":
		return "double"
	case "int", "integer":
		return "int"
	case "checkbox", "boolean":
		return "boolean"
	case "lookup", "master_detail", "masterdetail", "reference":
		return "reference"
	case "select", "picklist":
		return "picklist"
	case "multi_select", "multipicklist":
		return "multipicklist"
	case "anytype":
		return "anyType"
	case "currency", "percent", "date", "datetime", "email", "phone", "url", "encryptedstring", "location", "address":
		return value
	default:
		return "string"
	}
}

func describeFieldLength(field searchFieldSpec, fieldType string) int {
	if field.MaxLength != nil && *field.MaxLength > 0 {
		return *field.MaxLength
	}
	switch fieldType {
	case "id", "reference":
		return 18
	case "boolean", "double", "int", "currency", "percent":
		return 0
	case "textarea":
		return 32000
	case "multipicklist":
		return 4099
	case "encryptedstring":
		return 175
	default:
		return 255
	}
}

func describeRuntimeLookupInfo(
	field searchFieldSpec,
	referenceTo []string,
	source searchObjectSpec,
	specs map[string]searchObjectSpec,
	permissions permissionsemantic.Response,
) map[string]any {
	if !strings.EqualFold(strings.TrimSpace(field.Validator), runtimeScopedLookupRule) {
		return nil
	}
	unusable := func() map[string]any { return map[string]any{} }
	fieldType := describeFieldType(field)
	if fieldType != "reference" || len(field.ReferenceTo) != 1 ||
		len(referenceTo) != 1 || specs == nil {
		return unusable()
	}
	config, err := parseSearchLookupConfig(field.ValidatorConfig)
	if err != nil {
		return unusable()
	}
	target, found := specs[strings.ToLower(referenceTo[0])]
	if !found || !strings.EqualFold(field.ReferenceTo[0], target.APIName) {
		return unusable()
	}
	sourcePermissions := fieldPermissionsForDescribe(permissions, source.APIName)
	mappings := make([]map[string]any, 0, len(config.FilterMappings))
	for _, mapping := range config.FilterMappings {
		recordField, found := layoutFieldSpec(source, mapping.RecordField)
		recordPermission, recordReadable :=
			sourcePermissions[strings.ToLower(mapping.RecordField)]
		if !found || !recordReadable || !recordPermission.CanRead ||
			len(recordField.ReferenceTo) != 1 {
			return unusable()
		}
		parent, found := specs[strings.ToLower(recordField.ReferenceTo[0])]
		if !found || !strings.EqualFold(recordField.ReferenceTo[0], parent.APIName) {
			return unusable()
		}
		parentField, readable := describeReadableLookupMappingField(
			parent, mapping.SourceField, permissions, true,
		)
		if !readable {
			return unusable()
		}
		targetField, readable := describeReadableLookupMappingField(
			target, mapping.TargetField, permissions, false,
		)
		if !readable {
			return unusable()
		}
		mappings = append(mappings, map[string]any{
			"recordField": recordField.APIName,
			"sourceField": parentField,
			"targetField": targetField,
		})
	}
	return map[string]any{"filterMappings": mappings}
}

func describeReadableLookupMappingField(
	object searchObjectSpec,
	fieldName string,
	permissions permissionsemantic.Response,
	allowImplicitID bool,
) (string, bool) {
	if _, readable := objectPermissionForDescribe(permissions, object.APIName); !readable {
		return "", false
	}
	if allowImplicitID && strings.EqualFold(fieldName, "Id") {
		return "Id", true
	}
	field, found := layoutFieldSpec(object, fieldName)
	permission, readable := fieldPermissionsForDescribe(
		permissions, object.APIName,
	)[strings.ToLower(fieldName)]
	if !found || !readable || !permission.CanRead {
		return "", false
	}
	return field.APIName, true
}

func describeDefaultValue(field searchFieldSpec, fieldType string) any {
	if field.DefaultValue == nil {
		return nil
	}
	value := strings.TrimSpace(*field.DefaultValue)
	if len(value) >= 2 && value[0] == '\'' && value[len(value)-1] == '\'' {
		value = strings.ReplaceAll(value[1:len(value)-1], "''", "'")
	}
	switch fieldType {
	case "boolean":
		switch strings.ToLower(value) {
		case "1", "true", "t", "yes", "y":
			return true
		case "0", "false", "f", "no", "n":
			return false
		}
	case "int", "double", "currency", "percent":
		if number, err := strconv.ParseFloat(value, 64); err == nil {
			return number
		}
	}
	return value
}

func describePicklistValues(object searchObjectSpec, field searchFieldSpec) []any {
	if len(field.Options) == 0 {
		return []any{}
	}
	controllerValues, hasStaticDependency := describePicklistControllerValues(object, field)
	values := make([]any, 0, len(field.Options))
	for _, option := range field.Options {
		entry := map[string]any{
			"active": true, "label": option.Label, "value": option.Value,
			"defaultValue": field.DefaultValue != nil && *field.DefaultValue == option.Value,
		}
		if len(option.Tags) != 0 {
			entry["tags"] = append([]string(nil), option.Tags...)
		}
		if hasStaticDependency {
			validFor, ok := describePicklistValidFor(controllerValues, field.PicklistDependency, option.Value)
			if !ok {
				return []any{}
			}
			entry["validFor"] = validFor
		}
		values = append(values, entry)
	}
	return values
}

func describeAuthorizedPicklistValues(
	object searchObjectSpec,
	field searchFieldSpec,
	specs map[string]searchObjectSpec,
	permissions permissionsemantic.Response,
) []any {
	if len(field.PicklistValueSources) == 0 {
		return describePicklistValues(object, field)
	}
	if len(field.PicklistValueSources) != 1 || specs == nil {
		return []any{}
	}
	source := field.PicklistValueSources[0]
	sourceObject, found := specs[strings.ToLower(source.Object)]
	if !found || !strings.EqualFold(sourceObject.APIName, source.Object) ||
		!describeAuthorityIsCurrent(sourceObject) {
		return []any{}
	}
	if _, readable := objectPermissionForDescribe(permissions, sourceObject.APIName); !readable {
		return []any{}
	}
	sourcePermissions := fieldPermissionsForDescribe(permissions, sourceObject.APIName)
	sourcePermission, found := sourcePermissions[strings.ToLower(source.Field)]
	if !found || !sourcePermission.CanRead {
		return []any{}
	}
	var sourceField *searchFieldSpec
	for index := range sourceObject.Fields {
		candidate := &sourceObject.Fields[index]
		if strings.EqualFold(candidate.APIName, source.Field) {
			if sourceField != nil {
				return []any{}
			}
			sourceField = candidate
		}
	}
	if sourceField == nil || sourceField.APIName != source.Field ||
		describeFieldType(*sourceField) != "picklist" {
		return []any{}
	}
	// A formula field has no controller of its own. Mirror only the source
	// value domain and avoid attaching dependency bits for a hidden controller.
	authorizedSource := *sourceField
	authorizedSource.DefaultValue = nil
	authorizedSource.ControllingField = ""
	authorizedSource.PicklistDependency = nil
	return describePicklistValues(sourceObject, authorizedSource)
}

func describePicklistControllerValues(object searchObjectSpec, field searchFieldSpec) ([]string, bool) {
	controllerName := strings.TrimSpace(field.ControllingField)
	if controllerName == "" || len(field.PicklistDependency) == 0 {
		return nil, false
	}
	var controller *searchFieldSpec
	for index := range object.Fields {
		if strings.EqualFold(object.Fields[index].APIName, controllerName) {
			controller = &object.Fields[index]
			break
		}
	}
	if controller == nil || (describeFieldType(*controller) != "picklist" && describeFieldType(*controller) != "multipicklist") || len(controller.Options) == 0 {
		return nil, false
	}
	controllerValues := make([]string, 0, len(controller.Options))
	controllerSet := make(map[string]struct{}, len(controller.Options))
	for _, option := range controller.Options {
		if option.Value == "" {
			continue
		}
		controllerValues = append(controllerValues, option.Value)
		controllerSet[option.Value] = struct{}{}
	}
	dependentSet := make(map[string]struct{}, len(field.Options))
	for _, option := range field.Options {
		if option.Value != "" {
			dependentSet[option.Value] = struct{}{}
		}
	}
	if len(controllerValues) == 0 || len(dependentSet) == 0 {
		return nil, false
	}
	referenced := make(map[string]struct{}, len(dependentSet))
	for controllerValue, dependentValues := range field.PicklistDependency {
		if _, ok := controllerSet[controllerValue]; !ok {
			return nil, false
		}
		for _, dependentValue := range dependentValues {
			if _, ok := dependentSet[dependentValue]; !ok {
				return nil, false
			}
			referenced[dependentValue] = struct{}{}
		}
	}
	for dependentValue := range dependentSet {
		if _, ok := referenced[dependentValue]; !ok {
			return nil, false
		}
	}
	return controllerValues, true
}

func describePicklistValidFor(controllerValues []string, dependency map[string][]string, dependentValue string) (string, bool) {
	if len(controllerValues) == 0 || dependentValue == "" {
		return "", false
	}
	raw := make([]byte, (len(controllerValues)+7)/8)
	found := false
	for index, controllerValue := range controllerValues {
		for _, allowed := range dependency[controllerValue] {
			if allowed == dependentValue {
				raw[index/8] |= 0x80 >> (index % 8)
				found = true
				break
			}
		}
	}
	if !found {
		return "", false
	}
	return base64.StdEncoding.EncodeToString(raw), true
}

func (service *Service) readObjectDescribe(
	ctx context.Context,
	bearer string,
	version string,
	objectID string,
) (map[string]any, error) {
	view, specs, err := readObjectSpecs(ctx, service.appMetadataV3)
	if err != nil {
		return nil, err
	}
	spec, found := specs[strings.ToLower(objectID)]
	historyObjectName := ""
	if !found && querycodec.IsHistoryObject(objectID) {
		historyObjectName = objectID
		parentObjectName := querycodec.ParentObjectFromHistoryName(objectID)
		spec, found = specs[strings.ToLower(parentObjectName)]
		if found && querycodec.HistoryObjectName(spec.APIName) != objectID {
			found = false
		}
	}
	if !found {
		return nil, &permissionsemantic.Failure{Category: permissionsemantic.FailureMissing}
	}
	if !describeAuthorityIsCurrent(spec) {
		return nil, unavailableSearch()
	}
	revision := view.Receipts.CatalogRevision
	selection, err := objectDescribePermissionSelection(spec, specs)
	if err != nil {
		return nil, err
	}
	permissionRequest := permissionsemantic.Request{
		MinCatalogRevision: &revision,
		Selection:          selection,
	}
	permissions, err := service.permissionMetadata.readEffective(
		ctx, bearer, permissionRequest,
	)
	if err != nil {
		return nil, err
	}
	if err := permissionsemantic.ValidateResponseForRequest(permissionRequest, permissions); err != nil {
		return nil, err
	}
	if err := validateSearchMetadataAuthority(
		ctx, service.reconcileAppMetadataV3, view, permissions.Receipts,
	); err != nil {
		return nil, err
	}
	objectPermission, readable := objectPermissionForDescribe(permissions, spec.APIName)
	if !readable {
		return nil, &permissionsemantic.Failure{Category: permissionsemantic.FailureForbidden}
	}
	if historyObjectName != "" {
		if !historySchemaSupportsDescribe(spec) {
			return nil, &permissionsemantic.Failure{Category: permissionsemantic.FailureMissing}
		}
		return describeHistoryObjectProjection(
			version, historyObjectName, spec, permissions,
		), nil
	}
	listFields, listFieldReceipts, err := service.readCurrentObjectListFields(
		ctx, bearer, view, []string{spec.APIName},
	)
	if err != nil {
		return nil, err
	}
	if !sameAppMetadataAuthority(permissions.Receipts, listFieldReceipts) {
		return nil, unavailablePageLayout()
	}
	recordTypes, err := projectRecordTypes(view, permissions, spec.APIName)
	if err != nil {
		return nil, err
	}
	childRelationships, err := describeChildRelationships(spec, specs, permissions)
	if err != nil {
		return nil, err
	}
	return describeObjectProjectionWithSpecs(
		version, spec, objectPermission, permissions, recordTypes,
		listFields[strings.ToLower(spec.APIName)], childRelationships, specs,
	), nil
}

func describeAuthorityIsCurrent(spec searchObjectSpec) bool {
	// tableType is the additive generation fence published by controlplane
	// v0.2.46 after the complete describe facts. Field isSystem is sparse in the
	// current component: true is present and false is omitted.
	if spec.TableType == nil || strings.TrimSpace(*spec.TableType) == "" {
		return false
	}
	return true
}

func (service *Service) serveObjectDescribe(writer http.ResponseWriter, request *http.Request) bool {
	route, matched := matchObjectDescribeRoute(request.URL.EscapedPath())
	if !matched || service.appMetadataV3 == nil || service.permissionMetadata == nil {
		return false
	}
	if request.Method != http.MethodGet {
		writer.Header().Set("Allow", http.MethodGet)
		writeCRMError(writer, http.StatusMethodNotAllowed, crmwire.SFCodeInvalidRequest, "Method not allowed")
		return true
	}
	service.requests.Add(1)
	if service.draining.Load() {
		service.drainRejected.Add(1)
		service.failures.Add(1)
		writeCRMError(writer, http.StatusServiceUnavailable, crmwire.SFCodeUnknownException, "Service is draining")
		return true
	}
	bearer, ok := endUserBearer(request.Header.Values("Authorization"))
	if !ok {
		service.localRejected.Add(1)
		service.failures.Add(1)
		writeCRMError(writer, http.StatusUnauthorized, crmwire.SFCodeInvalidSessionID, "Session expired or invalid")
		return true
	}
	service.inFlight.Add(1)
	defer service.inFlight.Add(-1)
	ctx, cancel := context.WithTimeout(request.Context(), service.requestTimeout)
	defer cancel()
	var response map[string]any
	var err error
	if route.global {
		response, err = service.readGlobalDescribe(ctx, bearer, route.version)
	} else {
		response, err = service.readObjectDescribe(ctx, bearer, route.version, route.objectID)
	}
	if err != nil {
		service.failures.Add(1)
		writeSearchFailure(writer, err)
		return true
	}
	service.successes.Add(1)
	writeJSON(writer, http.StatusOK, response)
	return true
}
