package packs

import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"reflect"
	"sort"
	"strings"

	"github.com/nexuscrm/files"
	"github.com/nexuscrm/kernel/pkg/formula"
	"github.com/nexuscrm/metadata"
	"github.com/nexuscrm/persistence"
	"github.com/nexuscrm/shared/pkg/searchmetadata"
)

type persistedRuntimeDeclaration struct {
	objectPayloadsJSON         string
	relatedListRulesJSON       string
	searchScopeOrderJSON       string
	searchAllDefaultFieldsJSON string
	formulaFunctionBundlesJSON string
	startupShallowJSON         string
}

func (d persistedRuntimeDeclaration) ObjectPayloadsJSON() string   { return d.objectPayloadsJSON }
func (d persistedRuntimeDeclaration) RelatedListRulesJSON() string { return d.relatedListRulesJSON }
func (d persistedRuntimeDeclaration) SearchScopeOrderJSON() string { return d.searchScopeOrderJSON }
func (d persistedRuntimeDeclaration) SearchAllDefaultFieldsJSON() string {
	return d.searchAllDefaultFieldsJSON
}
func (d persistedRuntimeDeclaration) FormulaFunctionBundlesJSON() string {
	return d.formulaFunctionBundlesJSON
}
func (d persistedRuntimeDeclaration) StartupShallowDeclaredRowsJSON() string {
	return d.startupShallowJSON
}

func BuildPersistedRuntimeDeclaration(pack Pack) (persistedRuntimeDeclaration, error) {
	decl := buildRuntimeDeclaration(pack)

	objectPayloadsJSON, err := marshalRuntimeObjectSpecPayloads(decl.objectSpecPayloads)
	if err != nil {
		return persistedRuntimeDeclaration{}, fmt.Errorf("marshal runtime object spec declarations for pack %s: %w", pack.Name(), err)
	}
	relatedListRulesJSON, err := marshalJSONOrEmptyArray(decl.relatedListRules)
	if err != nil {
		return persistedRuntimeDeclaration{}, fmt.Errorf("marshal runtime related-list rules for pack %s: %w", pack.Name(), err)
	}
	searchScopeOrderJSON, err := marshalJSONOrEmptyArray(decl.searchScopeOrder)
	if err != nil {
		return persistedRuntimeDeclaration{}, fmt.Errorf("marshal runtime search-scope order for pack %s: %w", pack.Name(), err)
	}
	searchAllDefaultFieldsJSON, err := marshalJSONOrEmptyArray(decl.searchAllDefaultFields)
	if err != nil {
		return persistedRuntimeDeclaration{}, fmt.Errorf("marshal runtime search_all_default_fields for pack %s: %w", pack.Name(), err)
	}
	formulaFunctionBundlesJSON, err := marshalJSONOrEmptyArray(decl.formulaFunctionBundles)
	if err != nil {
		return persistedRuntimeDeclaration{}, fmt.Errorf("marshal runtime formula function bundles for pack %s: %w", pack.Name(), err)
	}
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(decl.startupShallowRows)
	if err != nil {
		return persistedRuntimeDeclaration{}, fmt.Errorf("marshal runtime startup shallow declarations for pack %s: %w", pack.Name(), err)
	}

	return persistedRuntimeDeclaration{
		objectPayloadsJSON:         objectPayloadsJSON,
		relatedListRulesJSON:       relatedListRulesJSON,
		searchScopeOrderJSON:       searchScopeOrderJSON,
		searchAllDefaultFieldsJSON: searchAllDefaultFieldsJSON,
		formulaFunctionBundlesJSON: formulaFunctionBundlesJSON,
		startupShallowJSON:         startupShallowJSON,
	}, nil
}

func marshalRuntimeStartupShallowDeclaredRows(rows []runtimeStartupShallowDeclaredRow) (string, error) {
	payload, err := json.Marshal(normalizeRuntimeStartupShallowDeclaredRows(rows))
	if err != nil {
		return "", err
	}
	return string(payload), nil
}

type persistedRuntimePack struct {
	name                   string
	objectPayloads         [][]byte
	relatedListRules       []metadata.RelatedListRule
	searchScopeOrder       []metadata.SearchScopeOrderItem
	searchAllDefaultFields []searchmetadata.SearchAllDefaultFieldsDeclaration
	formulaFunctionBundles []formula.FunctionBundle
	startupShallowRows     []runtimeStartupShallowDeclaredRow
	hrefRewriteFields      []files.HrefRewriteField
	ownedObjects           []string
}

func (p *persistedRuntimePack) Name() string { return p.name }

func (p *persistedRuntimePack) Category() Category { return AppPack }

func (p *persistedRuntimePack) Apply(context.Context, ApplyDeps) error { return nil }

func (p *persistedRuntimePack) Verify(context.Context, VerifyDeps) error { return nil }

func (p *persistedRuntimePack) RuntimeObjectSpecPayloads() [][]byte {
	out := make([][]byte, 0, len(p.objectPayloads))
	for _, payload := range p.objectPayloads {
		out = append(out, append([]byte(nil), payload...))
	}
	return out
}

func (p *persistedRuntimePack) RuntimeSearchScopeOrder() []metadata.SearchScopeOrderItem {
	return append([]metadata.SearchScopeOrderItem(nil), p.searchScopeOrder...)
}

func (p *persistedRuntimePack) RuntimeSearchAllDefaultFields() []searchmetadata.SearchAllDefaultFieldsDeclaration {
	return cloneSearchAllDefaultFieldsDeclarations(p.searchAllDefaultFields)
}

func (p *persistedRuntimePack) RuntimeFormulaFunctionBundles() []formula.FunctionBundle {
	return formula.CloneFunctionBundles(p.formulaFunctionBundles)
}

func (p *persistedRuntimePack) RuntimeStartupShallowDeclaredRows() []runtimeStartupShallowDeclaredRow {
	return append([]runtimeStartupShallowDeclaredRow(nil), p.startupShallowRows...)
}

func (p *persistedRuntimePack) RuntimeHrefRewriteFields() []files.HrefRewriteField {
	return append([]files.HrefRewriteField(nil), p.hrefRewriteFields...)
}

func (p *persistedRuntimePack) OwnedObjectAPINames() []string {
	return append([]string(nil), p.ownedObjects...)
}

func (p *persistedRuntimePack) RuntimeRelatedListRules() []metadata.RelatedListRule {
	return append([]metadata.RelatedListRule(nil), p.relatedListRules...)
}

type PersistedRuntimeDeclarationJSON struct {
	ObjectSpecs            string
	RelatedLists           string
	SearchScope            string
	SearchAllDefaultFields string
	FormulaFunctionBundles string
	StartupShallow         string
}

func (declaration PersistedRuntimeDeclarationJSON) LoadPack(name string) (Pack, error) {
	values := []struct {
		name string
		raw  string
	}{
		{name: "object spec", raw: declaration.ObjectSpecs},
		{name: "related list", raw: declaration.RelatedLists},
		{name: "search scope", raw: declaration.SearchScope},
		{name: "search-all default fields", raw: declaration.SearchAllDefaultFields},
		{name: "formula function bundle", raw: declaration.FormulaFunctionBundles},
		{name: "startup shallow", raw: declaration.StartupShallow},
	}
	for _, value := range values {
		var elements []json.RawMessage
		trimmed := strings.TrimSpace(value.raw)
		if trimmed == "" || trimmed == "null" || json.Unmarshal([]byte(trimmed), &elements) != nil {
			return nil, fmt.Errorf("parse persisted runtime %s declarations for pack %s: declaration must be an array", value.name, strings.TrimSpace(name))
		}
		for index, element := range elements {
			trimmedElement := strings.TrimSpace(string(element))
			if trimmedElement == "null" || trimmedElement == "{}" {
				return nil, fmt.Errorf("parse persisted runtime %s declarations for pack %s: row %d is malformed", value.name, strings.TrimSpace(name), index)
			}
		}
	}
	pack, err := loadPersistedRuntimePackWithRuntimeDeclarationsAndStartupParser(
		name,
		declaration.ObjectSpecs,
		declaration.RelatedLists,
		declaration.SearchScope,
		declaration.SearchAllDefaultFields,
		declaration.FormulaFunctionBundles,
		declaration.StartupShallow,
		unmarshalPersistedRuntimeStartupShallowDeclaredRowsStrict,
	)
	if err != nil {
		return nil, err
	}
	for index, row := range pack.startupShallowRows {
		if _, _, err := normalizeRuntimeStartupShallowDeclaredProjection(row); err != nil {
			return nil, fmt.Errorf("parse persisted runtime startup-shallow declarations for pack %s row %d: %w", strings.TrimSpace(name), index, err)
		}
		if !runtimeStartupShallowSupportsSemanticProjection(row.Kind) &&
			strings.TrimSpace(row.Projection) != "" && !json.Valid([]byte(row.Projection)) {
			return nil, fmt.Errorf("parse persisted runtime startup-shallow declarations for pack %s row %d: projection is malformed", strings.TrimSpace(name), index)
		}
	}
	return pack, nil
}

// LoadPackWithLegacyConnectorCalloutProfileProjectionSource loads one complete
// persisted declaration while bridging connector_callout_profile projections
// omitted by compilers predating that immutable projection. The caller must
// separately prove that source is the exact source identity of the persisted
// generation; this method requires the persisted and source connector key sets
// to match exactly and only fills projections for those existing rows.
func (declaration PersistedRuntimeDeclarationJSON) LoadPackWithLegacyConnectorCalloutProfileProjectionSource(name string, source Pack) (Pack, error) {
	name = strings.TrimSpace(name)
	if source == nil || name == "" || strings.TrimSpace(source.Name()) != name {
		return nil, fmt.Errorf("legacy connector callout projection source does not match pack %s", name)
	}
	rows, err := unmarshalPersistedRuntimeStartupShallowDeclaredRowsStrict(declaration.StartupShallow)
	if err != nil {
		return nil, fmt.Errorf("parse persisted runtime startup-shallow declarations for pack %s: %w", name, err)
	}
	sourceRows := make(map[string]runtimeStartupShallowDeclaredRow)
	for _, row := range buildRuntimeDeclaration(source).startupShallowRows {
		if row.Kind != ComponentKindConnectorCalloutProfile {
			continue
		}
		key := persistedRuntimeStartupShallowRowKey(row.Kind, row.BusinessKey)
		if _, duplicate := sourceRows[key]; duplicate {
			return nil, fmt.Errorf("legacy connector callout projection source for pack %s has duplicate %s", name, row.BusinessKey)
		}
		if _, _, err := normalizeRuntimeStartupShallowDeclaredProjection(row); err != nil {
			return nil, fmt.Errorf("legacy connector callout projection source for pack %s row %s is invalid: %w", name, row.BusinessKey, err)
		}
		sourceRows[key] = row
	}
	persistedRows := make(map[string]struct{}, len(sourceRows))
	for index := range rows {
		row := &rows[index]
		if row.Kind != ComponentKindConnectorCalloutProfile {
			continue
		}
		key := persistedRuntimeStartupShallowRowKey(row.Kind, row.BusinessKey)
		if _, duplicate := persistedRows[key]; duplicate {
			return nil, fmt.Errorf("persisted legacy connector callout declarations for pack %s have duplicate %s", name, row.BusinessKey)
		}
		persistedRows[key] = struct{}{}
		sourceRow, ok := sourceRows[key]
		if !ok {
			return nil, fmt.Errorf("legacy connector callout projection for pack %s row %s is missing exact source projection", name, row.BusinessKey)
		}
		if strings.TrimSpace(row.Projection) == "" {
			row.Projection = sourceRow.Projection
		}
	}
	for key, sourceRow := range sourceRows {
		if _, ok := persistedRows[key]; !ok {
			return nil, fmt.Errorf("legacy connector callout projection source for pack %s row %s is missing exact persisted declaration", name, sourceRow.BusinessKey)
		}
	}
	startupShallow, err := marshalRuntimeStartupShallowDeclaredRows(rows)
	if err != nil {
		return nil, fmt.Errorf("marshal bridged persisted runtime startup-shallow declarations for pack %s: %w", name, err)
	}
	declaration.StartupShallow = startupShallow
	expected, err := BuildPersistedRuntimeDeclaration(source)
	if err != nil {
		return nil, fmt.Errorf("build exact legacy connector callout projection source declaration for pack %s: %w", name, err)
	}
	if !persistedRuntimeJSONEqual(declaration.ObjectSpecs, expected.ObjectPayloadsJSON()) ||
		!persistedRuntimeJSONEqual(declaration.RelatedLists, expected.RelatedListRulesJSON()) ||
		!persistedRuntimeJSONEqual(declaration.SearchScope, expected.SearchScopeOrderJSON()) ||
		!persistedRuntimeJSONEqual(declaration.SearchAllDefaultFields, expected.SearchAllDefaultFieldsJSON()) ||
		!persistedRuntimeJSONEqual(declaration.FormulaFunctionBundles, expected.FormulaFunctionBundlesJSON()) ||
		!persistedRuntimeJSONEqual(declaration.StartupShallow, expected.StartupShallowDeclaredRowsJSON()) {
		return nil, fmt.Errorf("legacy connector callout projection for pack %s persisted Runtime declaration does not match the exact source declaration", name)
	}
	return declaration.LoadPack(name)
}

func LoadPersistedRuntimePack(name string, objectPayloadsJSON string, relatedListRulesJSON string, searchScopeOrderJSON string) (*persistedRuntimePack, error) {
	return LoadPersistedRuntimePackWithSearchAllDefaultFields(name, objectPayloadsJSON, relatedListRulesJSON, searchScopeOrderJSON, "[]")
}

func LoadPersistedRuntimePackWithSearchAllDefaultFields(name string, objectPayloadsJSON string, relatedListRulesJSON string, searchScopeOrderJSON string, searchAllDefaultFieldsJSON string) (*persistedRuntimePack, error) {
	return LoadPersistedRuntimePackWithSearchAllDefaultFieldsAndFormulaFunctionBundles(name, objectPayloadsJSON, relatedListRulesJSON, searchScopeOrderJSON, searchAllDefaultFieldsJSON, "[]")
}

func LoadPersistedRuntimePackWithSearchAllDefaultFieldsAndFormulaFunctionBundles(name string, objectPayloadsJSON string, relatedListRulesJSON string, searchScopeOrderJSON string, searchAllDefaultFieldsJSON string, formulaFunctionBundlesJSON string) (*persistedRuntimePack, error) {
	return loadPersistedRuntimePackWithRuntimeDeclarations(name, objectPayloadsJSON, relatedListRulesJSON, searchScopeOrderJSON, searchAllDefaultFieldsJSON, formulaFunctionBundlesJSON, "[]")
}

func LoadPersistedRuntimePackWithSearchAllDefaultFieldsAndStartupShallow(name string, objectPayloadsJSON string, relatedListRulesJSON string, searchScopeOrderJSON string, searchAllDefaultFieldsJSON string, startupShallowJSON string) (*persistedRuntimePack, error) {
	return loadPersistedRuntimePackWithRuntimeDeclarations(name, objectPayloadsJSON, relatedListRulesJSON, searchScopeOrderJSON, searchAllDefaultFieldsJSON, "[]", startupShallowJSON)
}

func loadPersistedRuntimePackWithRuntimeDeclarations(name string, objectPayloadsJSON string, relatedListRulesJSON string, searchScopeOrderJSON string, searchAllDefaultFieldsJSON string, formulaFunctionBundlesJSON string, startupShallowJSON string) (*persistedRuntimePack, error) {
	return loadPersistedRuntimePackWithRuntimeDeclarationsAndStartupParser(
		name,
		objectPayloadsJSON,
		relatedListRulesJSON,
		searchScopeOrderJSON,
		searchAllDefaultFieldsJSON,
		formulaFunctionBundlesJSON,
		startupShallowJSON,
		unmarshalRuntimeStartupShallowDeclaredRows,
	)
}

func loadPersistedRuntimePackWithRuntimeDeclarationsAndStartupParser(name string, objectPayloadsJSON string, relatedListRulesJSON string, searchScopeOrderJSON string, searchAllDefaultFieldsJSON string, formulaFunctionBundlesJSON string, startupShallowJSON string, parseStartupShallow func(string) ([]runtimeStartupShallowDeclaredRow, error)) (*persistedRuntimePack, error) {
	payloads, err := unmarshalRuntimeObjectSpecPayloads(objectPayloadsJSON)
	if err != nil {
		return nil, fmt.Errorf("parse persisted runtime object spec declarations for pack %s: %w", strings.TrimSpace(name), err)
	}
	rules := []metadata.RelatedListRule{}
	if err := unmarshalJSONRequiredArray(relatedListRulesJSON, &rules); err != nil {
		return nil, fmt.Errorf("parse persisted runtime related-list rules for pack %s: %w", strings.TrimSpace(name), err)
	}
	searchScope := []metadata.SearchScopeOrderItem{}
	if err := unmarshalJSONRequiredArray(searchScopeOrderJSON, &searchScope); err != nil {
		return nil, fmt.Errorf("parse persisted runtime search-scope order for pack %s: %w", strings.TrimSpace(name), err)
	}
	searchAllDefaults := []searchmetadata.SearchAllDefaultFieldsDeclaration{}
	if err := unmarshalJSONRequiredArray(searchAllDefaultFieldsJSON, &searchAllDefaults); err != nil {
		return nil, fmt.Errorf("parse persisted runtime search_all_default_fields for pack %s: %w", strings.TrimSpace(name), err)
	}
	formulaBundles := []formula.FunctionBundle{}
	if err := unmarshalJSONRequiredArray(formulaFunctionBundlesJSON, &formulaBundles); err != nil {
		return nil, fmt.Errorf("parse persisted runtime formula function bundles for pack %s: %w", strings.TrimSpace(name), err)
	}
	if err := formula.ValidateFunctionBundles(formulaBundles); err != nil {
		return nil, fmt.Errorf("validate persisted runtime formula function bundles for pack %s: %w", strings.TrimSpace(name), err)
	}
	ownedObjects, err := persistedRuntimeDeclaredObjectNamesFromPayloads(payloads, "persisted-runtime-declaration")
	if err != nil {
		return nil, fmt.Errorf("derive persisted runtime owned objects for pack %s: %w", strings.TrimSpace(name), err)
	}
	startupRows, err := parseStartupShallow(startupShallowJSON)
	if err != nil {
		return nil, fmt.Errorf("parse persisted runtime startup-shallow declarations for pack %s: %w", strings.TrimSpace(name), err)
	}
	hrefFields, err := hrefRewriteFieldsFromStartupShallowRows(startupRows)
	if err != nil {
		return nil, fmt.Errorf("parse persisted runtime href_rewrite_fields declarations for pack %s: %w", strings.TrimSpace(name), err)
	}
	return &persistedRuntimePack{
		name:                   strings.TrimSpace(name),
		objectPayloads:         payloads,
		relatedListRules:       rules,
		searchScopeOrder:       searchScope,
		searchAllDefaultFields: cloneSearchAllDefaultFieldsDeclarations(searchAllDefaults),
		formulaFunctionBundles: formula.CloneFunctionBundles(formulaBundles),
		startupShallowRows:     append([]runtimeStartupShallowDeclaredRow(nil), startupRows...),
		hrefRewriteFields:      hrefFields,
		ownedObjects:           ownedObjects,
	}, nil
}

func LoadActiveInstalledRuntimeDeclarations(ctx context.Context, db *sql.DB) ([]Pack, error) {
	return loadActiveInstalledRuntimeDeclarations(ctx, db, nil)
}

// LoadActiveInstalledRuntimeDeclarationsWithComponentKindRegistrationSet
// reconstructs source-verified declarations with distribution registrations.
func LoadActiveInstalledRuntimeDeclarationsWithComponentKindRegistrationSet(ctx context.Context, db *sql.DB, registrations ComponentKindRegistrationSet) ([]Pack, error) {
	return loadActiveInstalledRuntimeDeclarations(ctx, db, &registrations)
}

func loadActiveInstalledRuntimeDeclarations(ctx context.Context, db *sql.DB, registrations *ComponentKindRegistrationSet) ([]Pack, error) {
	activePacks, err := activeInstalledPackRows(ctx, db)
	if err != nil {
		return nil, err
	}
	formulaFunctionBundles, hasFormulaFunctionBundles, err := runtimeFormulaFunctionBundlesFromActiveInstalledRows(activePacks)
	if err != nil {
		return nil, err
	}
	packList := make([]Pack, 0, len(activePacks))
	for _, row := range activePacks {
		pack, err := loadRuntimePackFromActiveRowWithComponentKindRegistrationSet(ctx, db, row, formulaFunctionBundles, hasFormulaFunctionBundles, registrations)
		if err != nil {
			return nil, err
		}
		packList = append(packList, pack)
	}
	return packList, nil
}

func LoadActiveInstalledPersistedRuntimeDeclarations(ctx context.Context, db *sql.DB) ([]Pack, error) {
	return loadActiveInstalledPersistedRuntimeDeclarations(ctx, db)
}

// LoadActiveInstalledPersistedRelatedListRulesWithExecutor returns the
// effective installed-pack related-list declarations through the caller's
// database snapshot. Catalog publication uses this instead of the process
// cache so the declarations and every other metadata fact receive one
// immutable revision.
func LoadActiveInstalledPersistedRelatedListRulesWithExecutor(
	ctx context.Context,
	executor persistence.Executor,
) ([]metadata.RelatedListRule, error) {
	packList, err := loadActiveInstalledPersistedRuntimeDeclarations(ctx, executor)
	if err != nil {
		return nil, err
	}
	registrations := make([]runtimeMetadataRegistration, 0, len(packList))
	for _, pack := range packList {
		if pack == nil {
			continue
		}
		registrations = append(registrations, runtimeMetadataRegistration{
			pack:        pack,
			declaration: buildRuntimeDeclaration(pack),
		})
	}
	if err := validateRuntimeDeclarationRegistrations(registrations); err != nil {
		return nil, err
	}

	result := make([]metadata.RelatedListRule, 0)
	identityIndex := make(map[string]int)
	for _, registration := range registrations {
		for _, rule := range registration.declaration.relatedListRules {
			identity := strings.ToLower(strings.TrimSpace(rule.ParentObjectAPI)) + "\x00" +
				strings.ToLower(strings.TrimSpace(rule.ChildObjectAPI)) + "\x00" +
				strings.ToLower(strings.TrimSpace(rule.LookupField))
			if index, exists := identityIndex[identity]; exists {
				result[index] = rule
				continue
			}
			identityIndex[identity] = len(result)
			result = append(result, rule)
		}
	}
	return result, nil
}

func loadActiveInstalledPersistedRuntimeDeclarations(ctx context.Context, executor persistence.Executor) ([]Pack, error) {
	activePacks, err := activeInstalledPackRows(ctx, executor)
	if err != nil {
		return nil, err
	}
	packList := make([]Pack, 0, len(activePacks))
	for _, row := range activePacks {
		pack, err := loadPersistedRuntimePackFromRowWithoutSourceVerification(row)
		if err != nil {
			return nil, err
		}
		packList = append(packList, pack)
	}
	return packList, nil
}

func loadPersistedRuntimePackFromRowWithoutSourceVerification(row activeInstalledPackRow) (Pack, error) {
	if !row.runtimeObjectSpecDeclarations.Valid || !row.runtimeRelatedListRules.Valid || !row.runtimeSearchScopeOrder.Valid || !row.runtimeSearchAllDefaultFields.Valid {
		return nil, fmt.Errorf("installed pack %s is missing persisted runtime declaration", row.name)
	}
	return loadPersistedRuntimePackWithRuntimeDeclarations(
		row.name,
		row.runtimeObjectSpecDeclarations.String,
		row.runtimeRelatedListRules.String,
		row.runtimeSearchScopeOrder.String,
		row.runtimeSearchAllDefaultFields.String,
		row.runtimeFormulaFunctionBundles.String,
		startupShallowJSONFromActiveRow(row),
	)
}

func loadPersistedRuntimePackFromRow(ctx context.Context, db *sql.DB, row activeInstalledPackRow, formulaFunctionBundlesForValidation []formula.FunctionBundle, hasFormulaFunctionBundlesForValidation bool, registrations *ComponentKindRegistrationSet) (Pack, error) {
	if !row.runtimeObjectSpecDeclarations.Valid || !row.runtimeRelatedListRules.Valid || !row.runtimeSearchScopeOrder.Valid || !row.runtimeSearchAllDefaultFields.Valid {
		return nil, fmt.Errorf("installed pack %s is missing persisted runtime declaration", row.name)
	}
	if !hasVerifiableRuntimeDeclarationSourceIdentity(row) {
		return nil, fmt.Errorf("installed pack %s persisted runtime declaration is not source-backed active state; run setup apply-packs", row.name)
	}
	pack, err := resolveRuntimeDeclarationSourceBackedActivePack(ctx, db, row, formulaFunctionBundlesForValidation, hasFormulaFunctionBundlesForValidation, registrations)
	if err != nil {
		return nil, err
	}
	startupShallowJSON, err := persistedRuntimeStartupShallowSourceIdentityJSON(row, pack)
	if err != nil {
		return nil, err
	}
	if err := VerifyPersistedRuntimeDeclarationAgainstPackWithSearchAllDefaultFieldsAndFormulaFunctionBundles(
		row.name,
		row.runtimeObjectSpecDeclarations.String,
		row.runtimeRelatedListRules.String,
		row.runtimeSearchScopeOrder.String,
		row.runtimeSearchAllDefaultFields.String,
		row.runtimeFormulaFunctionBundles.String,
		startupShallowJSON,
		pack,
	); err != nil {
		if !PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmissionWithSearchAllDefaultFieldsAndFormulaFunctionBundles(
			row.name,
			row.runtimeObjectSpecDeclarations.String,
			row.runtimeRelatedListRules.String,
			row.runtimeSearchScopeOrder.String,
			row.runtimeSearchAllDefaultFields.String,
			row.runtimeFormulaFunctionBundles.String,
			startupShallowJSON,
			pack,
		) {
			return nil, err
		}
	}
	return loadPersistedRuntimePackWithRuntimeDeclarations(
		row.name,
		row.runtimeObjectSpecDeclarations.String,
		row.runtimeRelatedListRules.String,
		row.runtimeSearchScopeOrder.String,
		row.runtimeSearchAllDefaultFields.String,
		row.runtimeFormulaFunctionBundles.String,
		startupShallowJSON,
	)
}

func startupShallowJSONFromActiveRow(row activeInstalledPackRow) string {
	if row.hasRuntimeStartupShallow && row.runtimeStartupShallow.Valid {
		return row.runtimeStartupShallow.String
	}
	return "[]"
}

func persistedRuntimeStartupShallowSourceIdentityJSON(row activeInstalledPackRow, pack Pack) (string, error) {
	if row.hasRuntimeStartupShallow {
		return row.runtimeStartupShallow.String, nil
	}
	expected, err := BuildPersistedRuntimeDeclaration(pack)
	if err != nil {
		return "", fmt.Errorf("build persisted runtime declaration for installed pack %s: %w", row.name, err)
	}
	return expected.StartupShallowDeclaredRowsJSON(), nil
}

func loadRuntimePackFromActiveRow(ctx context.Context, db *sql.DB, row activeInstalledPackRow, formulaFunctionBundlesForValidation []formula.FunctionBundle, hasFormulaFunctionBundlesForValidation bool) (Pack, error) {
	return loadRuntimePackFromActiveRowWithComponentKindRegistrationSet(ctx, db, row, formulaFunctionBundlesForValidation, hasFormulaFunctionBundlesForValidation, nil)
}

func loadRuntimePackFromActiveRowWithComponentKindRegistrationSet(ctx context.Context, db *sql.DB, row activeInstalledPackRow, formulaFunctionBundlesForValidation []formula.FunctionBundle, hasFormulaFunctionBundlesForValidation bool, registrations *ComponentKindRegistrationSet) (Pack, error) {
	if row.runtimeObjectSpecDeclarations.Valid && row.runtimeRelatedListRules.Valid && row.runtimeSearchScopeOrder.Valid && row.runtimeSearchAllDefaultFields.Valid {
		pack, err := loadRuntimePackFromActiveRowFromSourceWhenBundled(ctx, db, row, formulaFunctionBundlesForValidation, hasFormulaFunctionBundlesForValidation, registrations)
		if err != nil {
			return nil, err
		}
		if pack != nil {
			return pack, nil
		}
		return loadPersistedRuntimePackFromRow(ctx, db, row, formulaFunctionBundlesForValidation, hasFormulaFunctionBundlesForValidation, registrations)
	}
	pack, err := resolveRuntimeDeclarationSourceBackedActivePack(ctx, db, row, formulaFunctionBundlesForValidation, hasFormulaFunctionBundlesForValidation, registrations)
	if err == nil {
		return pack, nil
	}
	if hasVerifiableRuntimeDeclarationSourceIdentity(row) {
		return nil, err
	}
	return nil, fmt.Errorf("installed pack %s is missing persisted runtime declaration", row.name)
}

func loadRuntimePackFromActiveRowForInstall(ctx context.Context, db *sql.DB, row activeInstalledPackRow, formulaFunctionBundlesForValidation []formula.FunctionBundle, hasFormulaFunctionBundlesForValidation bool, registrations *ComponentKindRegistrationSet) (Pack, error) {
	if row.runtimeObjectSpecDeclarations.Valid && row.runtimeRelatedListRules.Valid && row.runtimeSearchScopeOrder.Valid && row.runtimeSearchAllDefaultFields.Valid {
		pack, err := loadRuntimePackFromActiveRowFromSourceWhenBundled(ctx, db, row, formulaFunctionBundlesForValidation, hasFormulaFunctionBundlesForValidation, registrations)
		if err != nil {
			return nil, err
		}
		if pack != nil {
			return pack, nil
		}
		return loadPersistedRuntimePackFromRow(ctx, db, row, formulaFunctionBundlesForValidation, hasFormulaFunctionBundlesForValidation, registrations)
	}
	if !row.sourceKind.Valid || strings.TrimSpace(row.sourceKind.String) == "" || !row.sourceURI.Valid || strings.TrimSpace(row.sourceURI.String) == "" {
		return nil, fmt.Errorf("installed pack %s is missing persisted runtime declaration", row.name)
	}
	return resolveRuntimeDeclarationSourceBackedActivePack(ctx, db, row, formulaFunctionBundlesForValidation, hasFormulaFunctionBundlesForValidation, registrations)
}

// loadRuntimePackFromActiveRowFromSourceWhenBundled is a narrow upgrade bridge
// for active rows persisted before runtime_formula_bundles existed. If the
// source-backed pack now declares formula bundles, load the source pack so
// validation sees the new runtime fact instead of the old persisted projection.
//
// Death condition: delete this bridge once every supported active install row
// is required to persist runtime_formula_bundles and missing bundle rows fail
// persisted runtime declaration verification.
func loadRuntimePackFromActiveRowFromSourceWhenBundled(ctx context.Context, db *sql.DB, row activeInstalledPackRow, formulaFunctionBundlesForValidation []formula.FunctionBundle, hasFormulaFunctionBundlesForValidation bool, registrations *ComponentKindRegistrationSet) (Pack, error) {
	if row.hasRuntimeFormulaBundles {
		return nil, nil
	}
	if !row.runtimeObjectSpecDeclarations.Valid || !row.runtimeRelatedListRules.Valid ||
		!row.runtimeSearchScopeOrder.Valid || !row.runtimeSearchAllDefaultFields.Valid {
		return nil, nil
	}
	if !hasVerifiableRuntimeDeclarationSourceIdentity(row) {
		return nil, nil
	}
	pack, err := resolveRuntimeDeclarationSourceBackedActivePack(ctx, db, row, formulaFunctionBundlesForValidation, hasFormulaFunctionBundlesForValidation, registrations)
	if err != nil {
		return nil, err
	}
	bundler, ok := pack.(runtimeFormulaFunctionBundleProvider)
	if !ok {
		return nil, nil
	}
	if len(bundler.RuntimeFormulaFunctionBundles()) == 0 {
		return nil, nil
	}
	return pack, nil
}

func resolveRuntimeDeclarationSourceBackedActivePack(ctx context.Context, db *sql.DB, row activeInstalledPackRow, formulaFunctionBundlesForValidation []formula.FunctionBundle, hasFormulaFunctionBundlesForValidation bool, registrations *ComponentKindRegistrationSet) (Pack, error) {
	if !row.sourceKind.Valid || strings.TrimSpace(row.sourceKind.String) == "" ||
		!row.sourceURI.Valid || strings.TrimSpace(row.sourceURI.String) == "" ||
		!row.appliedPayloadHash.Valid || strings.TrimSpace(row.appliedPayloadHash.String) == "" {
		return nil, fmt.Errorf("installed pack %s runtime declaration is not source-backed active state; run setup apply-packs", row.name)
	}
	return resolveActiveInstalledRuntimePack(ctx, db, row, formulaFunctionBundlesForValidation, hasFormulaFunctionBundlesForValidation, registrations)
}

func hasVerifiableRuntimeDeclarationSourceIdentity(row activeInstalledPackRow) bool {
	return row.sourceKind.Valid && strings.TrimSpace(row.sourceKind.String) != "" &&
		row.sourceURI.Valid && strings.TrimSpace(row.sourceURI.String) != "" &&
		row.appliedPayloadHash.Valid && strings.TrimSpace(row.appliedPayloadHash.String) != ""
}

func VerifyPersistedRuntimeDeclarationAgainstPack(packName, objectPayloadsJSON, relatedListRulesJSON, searchScopeOrderJSON, startupShallowJSON string, pack Pack) error {
	return VerifyPersistedRuntimeDeclarationAgainstPackWithSearchAllDefaultFields(packName, objectPayloadsJSON, relatedListRulesJSON, searchScopeOrderJSON, "[]", startupShallowJSON, pack)
}

func VerifyPersistedRuntimeDeclarationAgainstPackWithSearchAllDefaultFields(packName, objectPayloadsJSON, relatedListRulesJSON, searchScopeOrderJSON, searchAllDefaultFieldsJSON, startupShallowJSON string, pack Pack) error {
	return VerifyPersistedRuntimeDeclarationAgainstPackWithSearchAllDefaultFieldsAndFormulaFunctionBundles(packName, objectPayloadsJSON, relatedListRulesJSON, searchScopeOrderJSON, searchAllDefaultFieldsJSON, "[]", startupShallowJSON, pack)
}

func VerifyPersistedRuntimeDeclarationAgainstPackWithSearchAllDefaultFieldsAndFormulaFunctionBundles(packName, objectPayloadsJSON, relatedListRulesJSON, searchScopeOrderJSON, searchAllDefaultFieldsJSON, formulaFunctionBundlesJSON, startupShallowJSON string, pack Pack) error {
	expected, err := BuildPersistedRuntimeDeclaration(pack)
	if err != nil {
		return fmt.Errorf("build persisted runtime declaration for installed pack %s: %w", packName, err)
	}
	// This is a narrow upgrade bridge for pre-record_type startup-shallow
	// declarations: only entirely missing record_type rows may be tolerated.
	// Present rows, blank projections, or projection drift still fail closed.
	startupShallowMatches := persistedRuntimeStartupShallowJSONEqual(startupShallowJSON, expected.StartupShallowDeclaredRowsJSON(), pack, nil) ||
		persistedRuntimeStartupShallowJSONEqual(startupShallowJSON, expected.StartupShallowDeclaredRowsJSON(), pack, persistedRuntimeStartupShallowRecordTypeMissingAllowedRows(pack))
	if !persistedRuntimeJSONEqual(objectPayloadsJSON, expected.ObjectPayloadsJSON()) ||
		!persistedRuntimeJSONEqual(relatedListRulesJSON, expected.RelatedListRulesJSON()) ||
		!persistedRuntimeJSONEqual(searchScopeOrderJSON, expected.SearchScopeOrderJSON()) ||
		!persistedRuntimeJSONEqual(searchAllDefaultFieldsJSON, expected.SearchAllDefaultFieldsJSON()) ||
		!persistedRuntimeJSONEqual(formulaFunctionBundlesJSON, expected.FormulaFunctionBundlesJSON()) ||
		!startupShallowMatches {
		return fmt.Errorf("installed pack %s persisted runtime declaration does not match source identity; run setup apply-packs", packName)
	}
	return nil
}

func PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmission(packName, objectPayloadsJSON, relatedListRulesJSON, searchScopeOrderJSON, startupShallowJSON string, pack Pack) bool {
	return PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmissionWithSearchAllDefaultFields(packName, objectPayloadsJSON, relatedListRulesJSON, searchScopeOrderJSON, "[]", startupShallowJSON, pack)
}

func PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmissionWithSearchAllDefaultFields(packName, objectPayloadsJSON, relatedListRulesJSON, searchScopeOrderJSON, searchAllDefaultFieldsJSON, startupShallowJSON string, pack Pack) bool {
	return PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmissionWithSearchAllDefaultFieldsAndFormulaFunctionBundles(packName, objectPayloadsJSON, relatedListRulesJSON, searchScopeOrderJSON, searchAllDefaultFieldsJSON, "[]", startupShallowJSON, pack)
}

func PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmissionWithSearchAllDefaultFieldsAndFormulaFunctionBundles(packName, objectPayloadsJSON, relatedListRulesJSON, searchScopeOrderJSON, searchAllDefaultFieldsJSON, formulaFunctionBundlesJSON, startupShallowJSON string, pack Pack) bool {
	expected, err := BuildPersistedRuntimeDeclaration(pack)
	if err != nil {
		return false
	}
	expectedStartupShallowJSON := expected.StartupShallowDeclaredRowsJSON()
	recordTypeAllowedRows := persistedRuntimeStartupShallowRecordTypeMissingAllowedRows(pack)
	legacyAllowedRows := persistedRuntimeStartupShallowMergeMissingAllowedRows(
		persistedRuntimeStartupShallowMissingAllowedRows(pack),
		recordTypeAllowedRows,
	)
	return persistedRuntimeJSONEqual(objectPayloadsJSON, expected.ObjectPayloadsJSON()) &&
		persistedRuntimeJSONEqual(relatedListRulesJSON, expected.RelatedListRulesJSON()) &&
		persistedRuntimeJSONEqual(searchScopeOrderJSON, expected.SearchScopeOrderJSON()) &&
		persistedRuntimeJSONEqual(searchAllDefaultFieldsJSON, expected.SearchAllDefaultFieldsJSON()) &&
		persistedRuntimeJSONEqual(formulaFunctionBundlesJSON, expected.FormulaFunctionBundlesJSON()) &&
		startupShallowJSON != "" &&
		!persistedRuntimeStartupShallowJSONEqual(startupShallowJSON, expectedStartupShallowJSON, pack, nil) &&
		!persistedRuntimeStartupShallowJSONEqual(startupShallowJSON, expectedStartupShallowJSON, pack, recordTypeAllowedRows) &&
		persistedRuntimeStartupShallowJSONEqual(startupShallowJSON, expectedStartupShallowJSON, pack, legacyAllowedRows)
}

func persistedRuntimeStartupShallowJSONEqual(actualJSON, expectedJSON string, pack Pack, missingAllowed map[string]struct{}) bool {
	if persistedRuntimeJSONEqual(actualJSON, expectedJSON) {
		return true
	}
	actual, err := unmarshalPersistedRuntimeStartupShallowDeclaredRowsStrict(actualJSON)
	if err != nil {
		return strings.TrimSpace(actualJSON) == "" && !persistedRuntimeStartupShallowExpectedRowsRequired(expectedJSON)
	}
	expected, err := unmarshalRuntimeStartupShallowDeclaredRows(expectedJSON)
	if err != nil {
		return false
	}
	actualIndex := 0
	for _, expectedRow := range expected {
		for actualIndex < len(actual) && persistedRuntimeStartupShallowIgnorableRetainedRow(actual[actualIndex], pack) {
			actualIndex++
		}
		if actualIndex < len(actual) &&
			actual[actualIndex].Kind == expectedRow.Kind &&
			actual[actualIndex].BusinessKey == expectedRow.BusinessKey {
			if !persistedRuntimeStartupShallowRowsEqual(actual[actualIndex], expectedRow) {
				return false
			}
			actualIndex++
			continue
		}
		if _, ok := missingAllowed[persistedRuntimeStartupShallowRowKey(expectedRow.Kind, expectedRow.BusinessKey)]; ok {
			continue
		}
		return false
	}
	for actualIndex < len(actual) {
		if !persistedRuntimeStartupShallowIgnorableRetainedRow(actual[actualIndex], pack) {
			return false
		}
		actualIndex++
	}
	return true
}

func persistedRuntimeStartupShallowIgnorableRetainedRow(row runtimeStartupShallowDeclaredRow, pack Pack) bool {
	return row.Kind == ComponentKindApprovalProcess ||
		persistedRuntimeStartupShallowLegacyInactiveValidationRule(row, pack)
}

func persistedRuntimeStartupShallowRowsEqual(actual, expected runtimeStartupShallowDeclaredRow) bool {
	if actual.Kind != expected.Kind || actual.BusinessKey != expected.BusinessKey {
		return false
	}
	if actual.Projection == expected.Projection {
		return true
	}
	if strings.TrimSpace(actual.Projection) == "" && persistedRuntimeStartupShallowAllowsLegacyProjectionlessEquality(actual.Kind) {
		return strings.TrimSpace(expected.Projection) != ""
	}
	if actual.Kind == ComponentKindConnectorPushContract {
		actualNormalized, _, err := normalizeRuntimeStartupShallowDeclaredProjection(actual)
		if err != nil {
			return false
		}
		expectedNormalized, _, err := normalizeRuntimeStartupShallowDeclaredProjection(expected)
		return err == nil && actualNormalized == expectedNormalized
	}
	return actual.Kind == ComponentKindListFields &&
		persistedRuntimeLegacyEmptyListFieldsProjectionEqual(actual, expected)
}

func persistedRuntimeStartupShallowAllowsLegacyProjectionlessEquality(kind ComponentKind) bool {
	switch kind {
	case ComponentKindPermission, ComponentKindValidationRule:
		return true
	default:
		return false
	}
}

func persistedRuntimeStartupShallowMissingAllowedRows(pack Pack) map[string]struct{} {
	sourcePack, ok := pack.(*SourceBackedPack)
	if !ok || sourcePack == nil {
		return nil
	}
	standaloneListFieldsObjects := map[string]struct{}{}
	allowed := map[string]struct{}{}
	for _, component := range sourcePack.components {
		if component == nil || component.Kind() != ComponentKindListFields {
			continue
		}
		payload, err := component.ExpectedPayload()
		if err != nil {
			return nil
		}
		rows, err := sourceBackedListFieldsProjection(payload, fmt.Sprintf("%s %s", component.Kind(), component.BusinessKey()))
		if err != nil {
			return nil
		}
		for _, row := range rows {
			objectAPIName := strings.ToLower(strings.TrimSpace(row.ObjectAPIName))
			if objectAPIName != "" {
				standaloneListFieldsObjects[objectAPIName] = struct{}{}
			}
		}
	}
	for _, component := range sourcePack.components {
		objectComponent, ok := component.(*sourceBackedObjectSpecComponent)
		if !ok || objectComponent == nil {
			continue
		}
		for _, spec := range objectComponent.specs {
			objectAPIName := strings.TrimSpace(spec.APIName)
			if objectAPIName == "" || spec.ListFields == nil {
				continue
			}
			if _, overridden := standaloneListFieldsObjects[strings.ToLower(objectAPIName)]; overridden {
				continue
			}
			allowed[persistedRuntimeStartupShallowRowKey(ComponentKindListFields, objectAPIName)] = struct{}{}
		}
	}
	return allowed
}

func persistedRuntimeStartupShallowRecordTypeMissingAllowedRows(pack Pack) map[string]struct{} {
	sourcePack, ok := pack.(*SourceBackedPack)
	if !ok || sourcePack == nil {
		return nil
	}
	allowed := map[string]struct{}{}
	for _, component := range sourcePack.components {
		if component == nil || component.Kind() != ComponentKindRecordType {
			continue
		}
		payload, err := component.ExpectedPayload()
		if err != nil {
			return nil
		}
		rows, err := sourceBackedRecordTypeProjection(payload, fmt.Sprintf("%s %s", component.Kind(), component.BusinessKey()), sourcePack.Name())
		if err != nil {
			return nil
		}
		for _, row := range rows {
			key := JoinComponentBusinessKey(row.ObjectAPIName, row.DeveloperName)
			if key != "" {
				allowed[persistedRuntimeStartupShallowRowKey(ComponentKindRecordType, key)] = struct{}{}
			}
		}
	}
	return allowed
}

func persistedRuntimeStartupShallowMergeMissingAllowedRows(left, right map[string]struct{}) map[string]struct{} {
	if len(left) == 0 {
		return right
	}
	if len(right) == 0 {
		return left
	}
	merged := make(map[string]struct{}, len(left)+len(right))
	for key := range left {
		merged[key] = struct{}{}
	}
	for key := range right {
		merged[key] = struct{}{}
	}
	return merged
}

func persistedRuntimeStartupShallowRowKey(kind ComponentKind, businessKey string) string {
	return string(ComponentKind(strings.TrimSpace(string(kind)))) + "\x00" + strings.TrimSpace(businessKey)
}

func persistedRuntimeStartupShallowExpectedRowsRequired(expectedJSON string) bool {
	expected, err := unmarshalRuntimeStartupShallowDeclaredRows(expectedJSON)
	return err == nil && len(expected) > 0
}

func unmarshalPersistedRuntimeStartupShallowDeclaredRowsStrict(raw string) ([]runtimeStartupShallowDeclaredRow, error) {
	trimmed := strings.TrimSpace(raw)
	if trimmed == "" {
		return nil, fmt.Errorf("missing persisted startup shallow declaration")
	}
	if trimmed == "null" {
		return nil, fmt.Errorf("persisted startup shallow declaration must be an array")
	}
	var messages []json.RawMessage
	if err := json.Unmarshal([]byte(trimmed), &messages); err != nil {
		return nil, err
	}
	rows := make([]runtimeStartupShallowDeclaredRow, 0, len(messages))
	for i, message := range messages {
		if strings.TrimSpace(string(message)) == "null" {
			return nil, fmt.Errorf("persisted startup shallow declaration row %d must be an object", i)
		}
		var row runtimeStartupShallowDeclaredRow
		if err := json.Unmarshal(message, &row); err != nil {
			return nil, fmt.Errorf("parse persisted startup shallow declaration row %d: %w", i, err)
		}
		row.Kind = ComponentKind(strings.TrimSpace(string(row.Kind)))
		row.BusinessKey = strings.TrimSpace(row.BusinessKey)
		row.Projection = strings.TrimSpace(row.Projection)
		if row.Kind == "" || row.BusinessKey == "" {
			return nil, fmt.Errorf("persisted startup shallow declaration row %d is missing kind or business key", i)
		}
		rows = append(rows, row)
	}
	return normalizeRuntimeStartupShallowDeclaredRows(rows), nil
}

func persistedRuntimeStartupShallowLegacyInactiveValidationRule(row runtimeStartupShallowDeclaredRow, pack Pack) bool {
	if row.Kind != ComponentKindValidationRule {
		return false
	}
	if strings.TrimSpace(row.Projection) == "" {
		return persistedRuntimeStartupShallowLegacyProjectionlessInactiveValidationRule(row, pack)
	}
	normalized, legacyBlankProjection, err := normalizeRuntimeStartupShallowDeclaredProjection(row)
	if err != nil || legacyBlankProjection || strings.TrimSpace(normalized) == "" {
		return false
	}
	var projection runtimeStartupShallowValidationRuleProjection
	if err := json.Unmarshal([]byte(normalized), &projection); err != nil {
		return false
	}
	if strings.TrimSpace(projection.ObjectAPIName) == "" ||
		strings.TrimSpace(projection.Name) == "" ||
		strings.TrimSpace(projection.Condition) == "" ||
		strings.TrimSpace(projection.ErrorMessage) == "" ||
		strings.TrimSpace(projection.OwnerPack) == "" {
		return false
	}
	return !projection.Active
}

func persistedRuntimeStartupShallowLegacyProjectionlessInactiveValidationRule(row runtimeStartupShallowDeclaredRow, pack Pack) bool {
	sourcePack, ok := pack.(*SourceBackedPack)
	if !ok || sourcePack == nil {
		return false
	}
	for _, component := range sourcePack.components {
		if component == nil || component.Kind() != ComponentKindValidationRule {
			continue
		}
		payload, err := component.ExpectedPayload()
		if err != nil {
			return false
		}
		rules, _, err := sourceBackedValidationRuleProjection(payload, fmt.Sprintf("%s %s", component.Kind(), component.BusinessKey()), sourcePack.Name())
		if err != nil {
			return false
		}
		for _, rule := range rules {
			if JoinComponentBusinessKey(strings.TrimSpace(rule.ObjectAPIName), strings.TrimSpace(rule.Name)) == row.BusinessKey {
				return !rule.Active
			}
		}
	}
	return false
}

func persistedRuntimeLegacyEmptyListFieldsProjectionEqual(actual, expected runtimeStartupShallowDeclaredRow) bool {
	actualProjection, actualFields, err := parsePersistedRuntimeListFieldsProjectionParts(actual)
	if err != nil {
		return false
	}
	expectedProjection, expectedFields, err := parsePersistedRuntimeListFieldsProjectionParts(expected)
	if err != nil {
		return false
	}
	if actualProjection.ObjectAPIName != actual.BusinessKey ||
		expectedProjection.ObjectAPIName != expected.BusinessKey ||
		actualProjection.ObjectAPIName != expectedProjection.ObjectAPIName {
		return false
	}
	return actualFields == "null" && expectedFields == "[]"
}

type persistedRuntimeListFieldsProjectionParts struct {
	ObjectAPIName string          `json:"objectApiName"`
	Fields        json.RawMessage `json:"fields"`
}

func parsePersistedRuntimeListFieldsProjectionParts(row runtimeStartupShallowDeclaredRow) (persistedRuntimeListFieldsProjectionParts, string, error) {
	var projection persistedRuntimeListFieldsProjectionParts
	if err := json.Unmarshal([]byte(row.Projection), &projection); err != nil {
		return persistedRuntimeListFieldsProjectionParts{}, "", err
	}
	return projection, strings.TrimSpace(string(projection.Fields)), nil
}

func persistedRuntimeJSONEqual(stored, expected string) bool {
	var storedValue any
	var expectedValue any
	if err := json.Unmarshal([]byte(strings.TrimSpace(stored)), &storedValue); err != nil {
		return strings.TrimSpace(stored) == strings.TrimSpace(expected)
	}
	if err := json.Unmarshal([]byte(strings.TrimSpace(expected)), &expectedValue); err != nil {
		return strings.TrimSpace(stored) == strings.TrimSpace(expected)
	}
	return reflect.DeepEqual(storedValue, expectedValue)
}

func marshalRuntimeObjectSpecPayloads(payloads [][]byte) (string, error) {
	raw := make([]json.RawMessage, 0, len(payloads))
	for _, payload := range payloads {
		trimmed := strings.TrimSpace(string(payload))
		if trimmed == "" {
			continue
		}
		raw = append(raw, json.RawMessage(trimmed))
	}
	data, err := json.Marshal(raw)
	if err != nil {
		return "", err
	}
	return string(data), nil
}

func unmarshalRuntimeObjectSpecPayloads(raw string) ([][]byte, error) {
	var messages []json.RawMessage
	if err := unmarshalJSONRequiredArray(raw, &messages); err != nil {
		return nil, err
	}
	payloads := make([][]byte, 0, len(messages))
	for _, message := range messages {
		payloads = append(payloads, append([]byte(nil), message...))
	}
	return payloads, nil
}

func marshalJSONOrEmptyArray(v any) (string, error) {
	data, err := json.Marshal(v)
	if err != nil {
		return "", err
	}
	if strings.TrimSpace(string(data)) == "null" {
		return "[]", nil
	}
	return string(data), nil
}

func unmarshalJSONRequiredArray(raw string, dst any) error {
	trimmed := strings.TrimSpace(raw)
	if trimmed == "" {
		return fmt.Errorf("missing persisted declaration payload")
	}
	return json.Unmarshal([]byte(trimmed), dst)
}

func persistedRuntimeDeclaredObjectNamesFromPayloads(payloads [][]byte, source string) ([]string, error) {
	specs, err := ParseObjectSpecsPayloads(payloads, source)
	if err != nil {
		return nil, err
	}
	seen := map[string]string{}
	for _, spec := range specs {
		name := strings.TrimSpace(spec.APIName)
		if name == "" {
			continue
		}
		seen[strings.ToLower(name)] = name
	}
	names := make([]string, 0, len(seen))
	for _, name := range seen {
		names = append(names, name)
	}
	sort.Strings(names)
	return names, nil
}
