package catalogreconcile

import (
	"context"
	"encoding/json"
	"errors"
	"strings"
	"testing"

	"github.com/nexuscrm/kernel/pkg/formula"
	"github.com/nexuscrm/metadata"
	"github.com/nexuscrm/metadata/catalogsnapshot"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/fieldprovenance"
	"github.com/nexuscrm/shared/pkg/models"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/recordsguard"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/auditlogv1"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/bulkingestv1"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/effectivepermissionsv1"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/flowv1"
	layoutauthoringv1 "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/layoutauthoringv1"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/listviewv1"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/pagelayoutresolutionv1"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/permissionauthoringv1"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/queryv1"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recorddefaultsv1"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recordmutationv1"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recyclebinmutationv1"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recyclebinv1"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/relatedcountsv1"
)

type transactionMarker struct{}

func TestCreateDefaultPreviewUsesMutationProjection(t *testing.T) {
	selection := MetadataSelection{RuntimeCapabilityIDs: []string{recorddefaultsv1.CapabilityName}}
	if !selectionIncludesMutationFacts(selection) {
		t.Fatal("create-default preview must compile the create/mutation metadata closure")
	}
	profile, err := projectionProfile(recorddefaultsv1.CapabilityName)
	if err != nil {
		t.Fatal(err)
	}
	if profile != catalogsnapshot.ProjectionRecordMutationV1 {
		t.Fatalf("create-default preview projection = %q", profile)
	}
}

func TestPrivateListViewUsesMutationProjection(t *testing.T) {
	selection := MetadataSelection{RuntimeCapabilityIDs: []string{listviewv1.CapabilityName}}
	if !selectionIncludesMutationFacts(selection) {
		t.Fatal("private ListView capability must compile the mutation metadata closure")
	}
	profile, err := projectionProfile(listviewv1.CapabilityName)
	if err != nil {
		t.Fatal(err)
	}
	if profile != catalogsnapshot.ProjectionRecordMutationV1 {
		t.Fatalf("private ListView projection = %q", profile)
	}
}

func TestBulkIngestUsesMutationProjection(t *testing.T) {
	selection := MetadataSelection{RuntimeCapabilityIDs: []string{bulkingestv1.CapabilityName}}
	if !selectionIncludesMutationFacts(selection) {
		t.Fatal("Bulk ingest capability must compile the mutation metadata closure")
	}
	profile, err := projectionProfile(bulkingestv1.CapabilityName)
	if err != nil {
		t.Fatal(err)
	}
	if profile != catalogsnapshot.ProjectionRecordMutationV1 {
		t.Fatalf("Bulk ingest projection = %q", profile)
	}
}

func TestRecycleBinMutationUsesMutationProjection(t *testing.T) {
	selection := MetadataSelection{RuntimeCapabilityIDs: []string{recyclebinmutationv1.CapabilityName}}
	if !selectionIncludesMutationFacts(selection) {
		t.Fatal("Recycle Bin mutation must compile the complete record-mutation metadata closure")
	}
	profile, err := projectionProfile(recyclebinmutationv1.CapabilityName)
	if err != nil {
		t.Fatal(err)
	}
	if profile != catalogsnapshot.ProjectionRecordMutationV1 {
		t.Fatalf("Recycle Bin mutation projection = %q", profile)
	}
}

func TestEffectivePermissionsUsesLeastPrivilegeProjection(t *testing.T) {
	profile, err := projectionProfile(effectivepermissionsv1.CapabilityName)
	if err != nil {
		t.Fatal(err)
	}
	if profile != catalogsnapshot.ProjectionEffectivePermissionsV1 {
		t.Fatalf("effective-permissions projection = %q", profile)
	}
}

func TestPermissionAuthoringUsesMutationProjection(t *testing.T) {
	selection := MetadataSelection{RuntimeCapabilityIDs: []string{
		permissionauthoringv1.CapabilityName,
	}}
	if !selectionIncludesMutationFacts(selection) {
		t.Fatal("Permission authoring must compile the complete record-mutation metadata closure")
	}
	profile, err := projectionProfile(permissionauthoringv1.CapabilityName)
	if err != nil {
		t.Fatal(err)
	}
	if profile != catalogsnapshot.ProjectionRecordMutationV1 {
		t.Fatalf("Permission authoring projection = %q", profile)
	}
}

func TestPageLayoutResolutionPublishesOneTransactionClosure(t *testing.T) {
	profile, err := projectionProfile(pagelayoutresolutionv1.CapabilityName)
	if err != nil {
		t.Fatal(err)
	}
	if profile != catalogsnapshot.ProjectionPageLayoutResolutionV1 {
		t.Fatalf("page-layout projection = %q", profile)
	}
	layout := &models.PageLayout{
		ID: "layout-work-item", ObjectAPIName: "WorkItem", LayoutName: "Work Item",
		Sections: []models.PageSection{}, HeaderActions: []models.ActionConfig{},
		QuickActions: []models.ActionConfig{}, RelatedLists: []models.RelatedListConfig{{
			ID: "virtual-children", Label: "Children", ObjectAPIName: "DisplayChild",
			LookupField: "ParentId", Fields: []string{"Name"},
		}},
	}
	profileID := "profile-session"
	recordTypeID := "rt-enterprise"
	reader := &markedReader{
		t: t, objects: []*models.ObjectMetadata{validObject("WorkItem"), validObject("DisplayChild"), validObject("QueryChild")},
		recordTypes: map[string][]*models.RecordType{
			"WorkItem": {{ID: recordTypeID, ObjectAPIName: "WorkItem", DeveloperName: "Enterprise", Name: "Enterprise", IsActive: true}},
		},
		layouts: map[string][]*models.PageLayout{"WorkItem": {layout}},
		layoutAssignments: map[string][]*models.LayoutAssignment{
			"WorkItem": {{
				ID: "assignment-profile-record-type", ObjectAPIName: "WorkItem", LayoutID: layout.ID,
				ProfileID: &profileID, RecordTypeID: &recordTypeID, Specificity: 2,
			}},
		},
		relatedListRules: []metadata.RelatedListRule{{
			ParentObjectAPI: "WorkItem", ChildObjectAPI: "DisplayChild", LookupField: "ParentId",
			Resolution: &metadata.RelatedListResolution{
				Query:  metadata.ResolvedQueryTarget{ObjectApiName: "QueryChild", LookupField: "WorkItemId"},
				Detail: metadata.ResolvedDetailTarget{ObjectApiName: "DisplayChild"},
				List:   metadata.ResolvedListTarget{ObjectApiName: "QueryChild", FilterField: "WorkItemId"},
				Create: metadata.ResolvedCreateTarget{Kind: "standard", ObjectApiName: "QueryChild", PrefillMappings: map[string]string{"WorkItemId": "Id"}},
			},
		}},
	}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityID: pagelayoutresolutionv1.CapabilityName,
		CatalogRevision:     7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	transactionCalls := 0
	effective, err := ReadEffectiveMetadata(
		context.Background(),
		func(ctx context.Context, fn func(context.Context) error) error {
			transactionCalls++
			return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
		},
		reader, selection, nil,
	)
	if err != nil {
		t.Fatal(err)
	}
	if transactionCalls != 1 {
		t.Fatalf("publication transactions = %d, want one", transactionCalls)
	}
	artifact, err := catalogsnapshot.CompileEffectiveMetadata(effective)
	if err != nil {
		t.Fatal(err)
	}
	snapshot, err := catalogsnapshot.OpenCatalogSnapshot(artifact)
	if err != nil {
		t.Fatal(err)
	}
	projected, err := catalogsnapshot.ProjectRuntimeMetadataView(snapshot, catalogsnapshot.ProjectionKey{
		AppInstallationID: "installation-test", CapabilityID: pagelayoutresolutionv1.CapabilityName,
	})
	if err != nil {
		t.Fatal(err)
	}
	view, err := catalogsnapshot.OpenRuntimeMetadataView(projected)
	if err != nil {
		t.Fatal(err)
	}
	resolved, related, err := view.ResolvePageLayout("WorkItem", profileID, nil, recordTypeID)
	if err != nil {
		t.Fatal(err)
	}
	if resolved.ID != layout.ID || len(related) != 1 ||
		related[0].Query.ObjectID != "QueryChild" ||
		related[0].ListTarget.ObjectID != "QueryChild" ||
		related[0].Create.PrefillMappings["WorkItemId"] != "Id" {
		t.Fatalf("published layout closure = %#v related=%#v", resolved, related)
	}
}

func TestPageLayoutResolutionRejectsRoleAssignmentWithoutExactSecurityAuthority(t *testing.T) {
	roleID := "role-sales"
	layout := &models.PageLayout{
		ID: "layout-work-item", ObjectAPIName: "WorkItem", LayoutName: "Work Item",
		Sections: []models.PageSection{}, HeaderActions: []models.ActionConfig{},
		QuickActions: []models.ActionConfig{}, RelatedLists: []models.RelatedListConfig{},
	}
	reader := &markedReader{
		t: t, objects: []*models.ObjectMetadata{validObject("WorkItem")},
		layouts: map[string][]*models.PageLayout{"WorkItem": {layout}},
		layoutAssignments: map[string][]*models.LayoutAssignment{
			"WorkItem": {{
				ID: "assignment-role", ObjectAPIName: "WorkItem", LayoutID: layout.ID,
				RoleID: &roleID, Specificity: 1,
			}},
		},
	}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityID: pagelayoutresolutionv1.CapabilityName,
		CatalogRevision:     7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	_, err := ReadEffectiveMetadata(
		context.Background(),
		func(ctx context.Context, fn func(context.Context) error) error {
			return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
		},
		reader,
		selection,
		nil,
	)
	if err == nil || !strings.Contains(err.Error(), "requires exact routing-security authority") {
		t.Fatalf("role assignment publication error = %v", err)
	}
}

func TestLayoutAuthoringPublishesStoredAggregateWithoutResolutionAuthority(t *testing.T) {
	profile, err := projectionProfile(layoutauthoringv1.CapabilityName)
	if err != nil {
		t.Fatal(err)
	}
	if profile != catalogsnapshot.ProjectionLayoutAuthoringV1 {
		t.Fatalf("Layout authoring projection = %q", profile)
	}

	roleID := "role-sales"
	layout := &models.PageLayout{
		ID: "layout-work-item", ObjectAPIName: "WorkItem", LayoutName: "Work Item",
		Type: "Create", Sections: []models.PageSection{}, HeaderActions: []models.ActionConfig{},
		QuickActions: []models.ActionConfig{}, RelatedLists: []models.RelatedListConfig{},
	}
	object := validObject("WorkItem")
	object.ListFields = []string{"Id"}
	reader := &markedReader{
		t: t, objects: []*models.ObjectMetadata{object},
		layouts: map[string][]*models.PageLayout{"WorkItem": {layout}},
		layoutAssignments: map[string][]*models.LayoutAssignment{
			"WorkItem": {
				{ID: "assignment-default", ObjectAPIName: "WorkItem", LayoutID: layout.ID},
				{ID: "assignment-role", ObjectAPIName: "WorkItem", LayoutID: layout.ID, RoleID: &roleID, Specificity: 1},
			},
		},
	}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityID: layoutauthoringv1.CapabilityName,
		CatalogRevision:     7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	effective, err := ReadEffectiveMetadata(
		context.Background(),
		func(ctx context.Context, fn func(context.Context) error) error {
			return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
		},
		reader,
		selection,
		nil,
	)
	if err != nil {
		t.Fatal(err)
	}
	if reader.aggregateReads != 1 || reader.layoutReadCalls != 0 || reader.assignmentReads != 0 {
		t.Fatalf("rendering reads must not supply stored Layout facts: layouts %d, assignments %d", reader.layoutReadCalls, reader.assignmentReads)
	}
	snapshotArtifact, err := catalogsnapshot.CompileEffectiveMetadata(effective)
	if err != nil {
		t.Fatal(err)
	}
	snapshot, err := catalogsnapshot.OpenCatalogSnapshot(snapshotArtifact)
	if err != nil {
		t.Fatal(err)
	}
	viewArtifact, err := catalogsnapshot.ProjectRuntimeMetadataView(snapshot, catalogsnapshot.ProjectionKey{
		AppInstallationID: "installation-test", CapabilityID: layoutauthoringv1.CapabilityName,
	})
	if err != nil {
		t.Fatal(err)
	}
	view, err := catalogsnapshot.OpenRuntimeMetadataView(viewArtifact)
	if err != nil {
		t.Fatal(err)
	}
	workspace, ok := view.LayoutAuthoringWorkspace("WorkItem")
	if !ok || len(workspace.Layouts) != 1 || len(workspace.Assignments) != 2 ||
		!workspace.Layouts[0].IsDefault {
		t.Fatalf("published Layout authoring workspace = %#v, present=%t", workspace, ok)
	}
	foundRole := false
	for _, assignment := range workspace.Assignments {
		if assignment.Selectors.RoleID != nil && *assignment.Selectors.RoleID == roleID {
			foundRole = true
		}
	}
	if !foundRole {
		t.Fatalf("published Layout authoring assignments lost Role selector: %#v", workspace.Assignments)
	}
}

func TestLayoutResolutionDoesNotPromoteStoredCreateLayout(t *testing.T) {
	for _, capabilities := range [][]string{
		{layoutauthoringv1.CapabilityName},
		{pagelayoutresolutionv1.CapabilityName},
		{layoutauthoringv1.CapabilityName, pagelayoutresolutionv1.CapabilityName},
	} {
		t.Run(strings.Join(capabilities, "+"), func(t *testing.T) {
			reader := &markedReader{t: t, objects: []*models.ObjectMetadata{validObject("WorkItem")},
				layouts:           map[string][]*models.PageLayout{"WorkItem": {{ID: "legacy-create", ObjectAPIName: "WorkItem", LayoutName: "Legacy", Type: "Create"}}},
				layoutAssignments: map[string][]*models.LayoutAssignment{"WorkItem": {{ID: "default-legacy", ObjectAPIName: "WorkItem", LayoutID: "legacy-create"}}},
			}
			_, err := ReadEffectiveMetadata(t.Context(), func(ctx context.Context, read func(context.Context) error) error {
				return read(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
			}, reader, MetadataSelection{OrgID: "org-test", AppInstallationID: "installation-test", RuntimeCapabilityID: capabilities[0], RuntimeCapabilityIDs: capabilities, CatalogRevision: 7, SchemaGeneration: 8, EngineGeneration: 9}, nil)
			if len(capabilities) == 1 && capabilities[0] == layoutauthoringv1.CapabilityName {
				if err != nil {
					t.Fatalf("authoring lost stored Create layout: %v", err)
				}
			} else if err == nil || !strings.Contains(err.Error(), "assignment target is missing") {
				t.Fatalf("resolution promoted an ineligible stored layout: %v", err)
			}
		})
	}
}

func TestLayoutAuthoringAndResolutionShareOneStoredFactRead(t *testing.T) {
	layout := &models.PageLayout{
		ID: "layout-work-item", ObjectAPIName: "WorkItem", LayoutName: "Work Item",
		Sections: []models.PageSection{}, HeaderActions: []models.ActionConfig{},
		QuickActions: []models.ActionConfig{}, RelatedLists: []models.RelatedListConfig{},
	}
	reader := &markedReader{
		t: t, objects: []*models.ObjectMetadata{validObject("WorkItem")},
		layouts: map[string][]*models.PageLayout{"WorkItem": {layout}},
		layoutAssignments: map[string][]*models.LayoutAssignment{
			"WorkItem": {{ID: "assignment-default", ObjectAPIName: "WorkItem", LayoutID: layout.ID}},
		},
	}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityID: pagelayoutresolutionv1.CapabilityName,
		RuntimeCapabilityIDs: []string{
			layoutauthoringv1.CapabilityName,
			pagelayoutresolutionv1.CapabilityName,
		},
		CatalogRevision: 7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	effective, err := ReadEffectiveMetadata(
		context.Background(),
		func(ctx context.Context, fn func(context.Context) error) error {
			return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
		},
		reader,
		selection,
		nil,
	)
	if err != nil {
		t.Fatal(err)
	}
	if reader.aggregateReads != 1 || reader.layoutReadCalls != 0 || reader.assignmentReads != 0 {
		t.Fatalf("combined publication used rendering reads: layouts %d, assignments %d", reader.layoutReadCalls, reader.assignmentReads)
	}
	snapshotArtifact, err := catalogsnapshot.CompileEffectiveMetadata(effective)
	if err != nil {
		t.Fatalf("shared stored Layout inputs were duplicated: %v", err)
	}
	snapshot, err := catalogsnapshot.OpenCatalogSnapshot(snapshotArtifact)
	if err != nil {
		t.Fatal(err)
	}
	for _, capabilityID := range []string{
		layoutauthoringv1.CapabilityName,
		pagelayoutresolutionv1.CapabilityName,
	} {
		if _, err := catalogsnapshot.ProjectRuntimeMetadataView(snapshot, catalogsnapshot.ProjectionKey{
			AppInstallationID: "installation-test", CapabilityID: capabilityID,
		}); err != nil {
			t.Fatalf("project shared stored Layout facts for %q: %v", capabilityID, err)
		}
	}
}

// Storage is the independent oracle: shape.ListFields and the rendering
// reader intentionally disagree with the stored aggregate.
func TestLayoutPublicationPreservesStoredCollectionsAndObjectScope(t *testing.T) {
	for _, capabilities := range [][]string{
		{layoutauthoringv1.CapabilityName},
		{pagelayoutresolutionv1.CapabilityName},
		{layoutauthoringv1.CapabilityName, pagelayoutresolutionv1.CapabilityName},
	} {
		t.Run(strings.Join(capabilities, "+"), func(t *testing.T) {
			object, empty := validObject("WorkItem"), validObject("EmptyItem")
			object.ListFields = []string{"Id"}
			empty.ListFields = []string{"Id"}
			layout := &models.PageLayout{ID: "stored-layout", ObjectAPIName: "WorkItem", LayoutName: "Stored", Type: "Detail"}
			reader := &markedReader{t: t, objects: []*models.ObjectMetadata{object, empty}, storedAggregates: map[string]*models.LayoutAuthoringAggregate{
				"WorkItem":  {ObjectAPIName: "WorkItem", OrderedListFields: []string{}, Layouts: []*models.PageLayout{layout}, Assignments: []*models.LayoutAssignment{{ID: "stored-default", ObjectAPIName: "WorkItem", LayoutID: layout.ID}}},
				"EmptyItem": {ObjectAPIName: "EmptyItem", OrderedListFields: []string{}, Layouts: []*models.PageLayout{}, Assignments: []*models.LayoutAssignment{}},
			}}
			effective, err := ReadEffectiveMetadata(t.Context(), func(ctx context.Context, read func(context.Context) error) error {
				return read(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
			}, reader, MetadataSelection{OrgID: "org-test", AppInstallationID: "installation-test", RuntimeCapabilityID: capabilities[0], RuntimeCapabilityIDs: capabilities, CatalogRevision: 7, SchemaGeneration: 8, EngineGeneration: 9}, nil)
			if err != nil {
				t.Fatal(err)
			}
			if reader.aggregateReads != 2 || reader.layoutReadCalls != 0 || reader.assignmentReads != 0 {
				t.Fatalf("stored=%d rendering=%d assignments=%d", reader.aggregateReads, reader.layoutReadCalls, reader.assignmentReads)
			}
			artifact, err := catalogsnapshot.CompileEffectiveMetadata(effective)
			if err != nil {
				t.Fatal(err)
			}
			snapshot, err := catalogsnapshot.OpenCatalogSnapshot(artifact)
			if err != nil {
				t.Fatal(err)
			}
			for _, capability := range capabilities {
				projected, err := catalogsnapshot.ProjectRuntimeMetadataView(snapshot, catalogsnapshot.ProjectionKey{AppInstallationID: "installation-test", CapabilityID: capability})
				if err != nil {
					t.Fatal(err)
				}
				view, err := catalogsnapshot.OpenRuntimeMetadataView(projected)
				if err != nil {
					t.Fatal(err)
				}
				if capability == layoutauthoringv1.CapabilityName {
					stored, ok := view.LayoutAuthoringStoredLayout("stored-layout")
					if !ok || len(stored.OrderedListFields) != 0 {
						t.Fatalf("stored empty ListFields lost: %#v", stored)
					}

					for _, name := range []string{"WorkItem", "EmptyItem"} {
						workspace, ok := view.LayoutAuthoringWorkspace(name)
						if !ok {
							t.Fatalf("%s stored empty list fields lost: %#v", name, workspace)
						}
						if name == "WorkItem" && (len(workspace.Layouts) != 1 || len(workspace.Assignments) != 1) {
							t.Fatalf("stored workspace lost: %#v", workspace)
						}
						if name == "EmptyItem" && (len(workspace.Layouts) != 0 || len(workspace.Assignments) != 0) {
							t.Fatalf("workspace crossed object scope: %#v", workspace)
						}
					}
				} else {
					layout, _, err := view.ResolvePageLayout("WorkItem", "profile", nil, "")
					if err != nil || layout.ID != "stored-layout" {
						t.Fatalf("stored resolution = %#v, %v", layout, err)
					}
				}
			}
		})
	}
}

func TestAuditLogReadUsesPermissionProjection(t *testing.T) {
	profile, err := projectionProfile(auditlogv1.CapabilityName)
	if err != nil {
		t.Fatal(err)
	}
	if profile != catalogsnapshot.ProjectionEffectivePermissionsV1 {
		t.Fatalf("audit-log read projection = %q", profile)
	}
}

type markedReader struct {
	t                 *testing.T
	sharingCalls      int
	recordTypeCalls   int
	objects           []*models.ObjectMetadata
	relationships     []*models.Relationship
	validationRules   []*models.ValidationRule
	recordTypes       map[string][]*models.RecordType
	flowDefinitions   []*models.FlowDefinition
	flowVersions      map[string][]*models.FlowVersion
	subscriptions     []catalogsnapshot.TriggerSubscription
	autoNumberRules   []catalogsnapshot.AutoNumberRule
	autoNumberReads   int
	fieldMappings     []catalogsnapshot.FieldMappingRule
	guardEntries      map[string][]recordsguard.CreateFromSourceGuardEntry
	searchScope       []metadata.SearchScopeOrderItem
	searchAllFields   []searchAllDefaultFieldsDeclaration
	applications      []*models.AppConfig
	formulaBundles    []formula.FunctionBundle
	layouts           map[string][]*models.PageLayout
	layoutAssignments map[string][]*models.LayoutAssignment
	relatedListRules  []metadata.RelatedListRule
	flowReadCalls     int
	fieldMappingCalls int
	layoutReadCalls   int
	assignmentReads   int
	aggregateReads    int
	storedAggregates  map[string]*models.LayoutAuthoringAggregate
}

func (r *markedReader) requireTransaction(ctx context.Context) {
	r.t.Helper()
	if marker, ok := ctx.Value(transactionMarker{}).(string); !ok || marker != "one-snapshot" {
		r.t.Fatal("metadata read escaped the reconcile transaction")
	}
}

func (r *markedReader) GetAllSchemas(ctx context.Context) ([]*models.ObjectMetadata, error) {
	r.requireTransaction(ctx)
	return r.objects, nil
}

func (r *markedReader) GetAllRelationships(ctx context.Context) ([]*models.Relationship, error) {
	r.requireTransaction(ctx)
	return r.relationships, nil
}

func (r *markedReader) GetSharingRules(ctx context.Context, objectAPIName string) ([]*models.SharingRule, error) {
	r.requireTransaction(ctx)
	r.sharingCalls++
	return nil, nil
}

func (r *markedReader) GetAllValidationRules(ctx context.Context) ([]*models.ValidationRule, error) {
	r.requireTransaction(ctx)
	return r.validationRules, nil
}

func (r *markedReader) GetRecordTypes(ctx context.Context, objectAPIName string) ([]*models.RecordType, error) {
	r.requireTransaction(ctx)
	r.recordTypeCalls++
	return r.recordTypes[objectAPIName], nil
}

type bulkMarkedReader struct {
	*markedReader
	allSharingRules  []*models.SharingRule
	allRecordTypes   []*models.RecordType
	sharingBulkCalls int
	recordBulkCalls  int
}

func (r *bulkMarkedReader) GetAllSharingRules(ctx context.Context) ([]*models.SharingRule, error) {
	r.requireTransaction(ctx)
	r.sharingBulkCalls++
	return r.allSharingRules, nil
}

func (r *bulkMarkedReader) GetAllRecordTypes(ctx context.Context) ([]*models.RecordType, error) {
	r.requireTransaction(ctx)
	r.recordBulkCalls++
	return r.allRecordTypes, nil
}

func (r *markedReader) GetAllFlowDefinitions(ctx context.Context) ([]*models.FlowDefinition, error) {
	r.requireTransaction(ctx)
	r.flowReadCalls++
	return r.flowDefinitions, nil
}

func (r *markedReader) GetFlowVersions(ctx context.Context, definitionID string) ([]*models.FlowVersion, error) {
	r.requireTransaction(ctx)
	return r.flowVersions[definitionID], nil
}

func (r *markedReader) GetActiveTriggerSubscriptions(ctx context.Context) ([]catalogsnapshot.TriggerSubscription, error) {
	r.requireTransaction(ctx)
	return r.subscriptions, nil
}

func (r *markedReader) GetAutoNumberRules(ctx context.Context) ([]catalogsnapshot.AutoNumberRule, error) {
	r.requireTransaction(ctx)
	r.autoNumberReads++
	return r.autoNumberRules, nil
}

func (r *markedReader) GetFieldMappingRules(ctx context.Context) ([]catalogsnapshot.FieldMappingRule, error) {
	r.requireTransaction(ctx)
	r.fieldMappingCalls++
	return r.fieldMappings, nil
}

func (r *markedReader) GetCreateFromSourceGuardEntries(ctx context.Context, targetObject string) ([]recordsguard.CreateFromSourceGuardEntry, error) {
	r.requireTransaction(ctx)
	return r.guardEntries[targetObject], nil
}

func (r *markedReader) GetRuntimeSearchAllDefaultFields(
	ctx context.Context,
) ([]searchAllDefaultFieldsDeclaration, error) {
	r.requireTransaction(ctx)
	return r.searchAllFields, nil
}

func (r *markedReader) GetApplicationDefinitions(ctx context.Context) ([]*models.AppConfig, error) {
	r.requireTransaction(ctx)
	return r.applications, nil
}

func (r *markedReader) GetRuntimeFormulaFunctionBundles(ctx context.Context) ([]formula.FunctionBundle, error) {
	r.requireTransaction(ctx)
	return formula.CloneFunctionBundles(r.formulaBundles), nil
}

func (r *markedReader) GetLayouts(ctx context.Context, objectAPIName string) ([]*models.PageLayout, error) {
	r.requireTransaction(ctx)
	r.layoutReadCalls++
	return r.layouts[objectAPIName], nil
}

func (r *markedReader) ReadLayoutAuthoringAggregate(ctx context.Context, objectAPIName string) (*models.LayoutAuthoringAggregate, error) {
	r.requireTransaction(ctx)
	r.aggregateReads++
	if r.storedAggregates != nil {
		return r.storedAggregates[objectAPIName], nil
	}
	for _, object := range r.objects {
		if object.APIName == objectAPIName {
			return &models.LayoutAuthoringAggregate{
				ObjectAPIName: objectAPIName, OrderedListFields: append([]string{}, object.ListFields...),
				Layouts: append([]*models.PageLayout{}, r.layouts[objectAPIName]...), Assignments: append([]*models.LayoutAssignment{}, r.layoutAssignments[objectAPIName]...),
			}, nil
		}
	}
	return nil, errors.New("object absent from stored Layout fixture")
}

func (r *markedReader) GetAssignmentsForObject(ctx context.Context, objectAPIName string) ([]*models.LayoutAssignment, error) {
	r.requireTransaction(ctx)
	r.assignmentReads++
	return r.layoutAssignments[objectAPIName], nil
}

func (r *markedReader) GetRuntimeRelatedListRules(ctx context.Context) ([]metadata.RelatedListRule, error) {
	r.requireTransaction(ctx)
	return r.relatedListRules, nil
}

func TestReadEffectiveMetadataUsesBulkObjectScopedReadsWhenAvailable(t *testing.T) {
	base := &markedReader{
		t:       t,
		objects: []*models.ObjectMetadata{validObject("Account"), validObject("Contact")},
	}
	reader := &bulkMarkedReader{
		markedReader: base,
	}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityID: "runtime.records.mutate.v1",
		CatalogRevision:     7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	_, err := ReadEffectiveMetadata(context.Background(), func(ctx context.Context, fn func(context.Context) error) error {
		return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
	}, reader, selection, nil)
	if err != nil {
		t.Fatal(err)
	}
	if reader.sharingBulkCalls != 1 || reader.recordBulkCalls != 1 {
		t.Fatalf("bulk calls = sharing:%d record:%d, want one each", reader.sharingBulkCalls, reader.recordBulkCalls)
	}
	if base.sharingCalls != 0 || base.recordTypeCalls != 0 {
		t.Fatalf("per-object calls = sharing:%d record:%d, want zero", base.sharingCalls, base.recordTypeCalls)
	}
}

func TestReadEffectiveMetadataPublishesPermissionRecordTypesWithoutMutationClosure(t *testing.T) {
	reader := &markedReader{
		t:       t,
		objects: []*models.ObjectMetadata{validObject("WorkItem"), validObject("Workspace")},
		recordTypes: map[string][]*models.RecordType{
			"WorkItem": {
				{ID: "rt-active", ObjectAPIName: "WorkItem", DeveloperName: "Active", Name: "Active", IsActive: true},
				{ID: "rt-inactive", ObjectAPIName: "WorkItem", DeveloperName: "Inactive", Name: "Inactive", IsActive: false},
			},
		},
	}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityID: effectivepermissionsv1.CapabilityName,
		CatalogRevision:     7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	transactions := 0
	effective, err := ReadEffectiveMetadata(
		context.Background(),
		func(ctx context.Context, fn func(context.Context) error) error {
			transactions++
			return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
		},
		reader,
		selection,
		nil,
	)
	if err != nil {
		t.Fatal(err)
	}
	if transactions != 1 || reader.recordTypeCalls != 2 || reader.flowReadCalls != 0 {
		t.Fatalf(
			"permission-only reads = transactions:%d recordTypes:%d flows:%d",
			transactions, reader.recordTypeCalls, reader.flowReadCalls,
		)
	}
	snapshotArtifact, err := catalogsnapshot.CompileEffectiveMetadata(effective)
	if err != nil {
		t.Fatal(err)
	}
	snapshot, err := catalogsnapshot.OpenCatalogSnapshot(snapshotArtifact)
	if err != nil {
		t.Fatal(err)
	}
	viewArtifact, err := catalogsnapshot.ProjectRuntimeMetadataView(
		snapshot,
		catalogsnapshot.ProjectionKey{
			AppInstallationID: selection.AppInstallationID,
			CapabilityID:      effectivepermissionsv1.CapabilityName,
		},
	)
	if err != nil {
		t.Fatal(err)
	}
	view, err := catalogsnapshot.OpenRuntimeMetadataView(viewArtifact)
	if err != nil {
		t.Fatal(err)
	}
	workItem, ok := view.EffectivePermissionObject("WorkItem")
	if !ok || !view.SupportsEffectivePermissionServing() ||
		view.Lineage().CatalogRevision != 7 || len(view.Objects()) != 2 || len(workItem.FieldNames) != 0 ||
		len(workItem.RecordTypes) != 1 || workItem.RecordTypes[0].RecordTypeID != "rt-active" {
		t.Fatalf("permission-only view = %#v object=%#v found=%t", view, workItem, ok)
	}
}

func TestReadEffectiveMetadataMutationAndPermissionShareOneRecordTypeRead(t *testing.T) {
	base := &markedReader{
		t:       t,
		objects: []*models.ObjectMetadata{validObject("WorkItem"), validObject("Workspace")},
	}
	reader := &bulkMarkedReader{
		markedReader: base,
		allRecordTypes: []*models.RecordType{{
			ID: "rt-active", ObjectAPIName: "WorkItem",
			DeveloperName: "Active", Name: "Active", IsActive: true,
		}},
	}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityIDs: []string{
			recordmutationv1.CapabilityName,
			effectivepermissionsv1.CapabilityName,
		},
		CatalogRevision: 7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	transactions := 0
	effective, err := ReadEffectiveMetadata(
		context.Background(),
		func(ctx context.Context, fn func(context.Context) error) error {
			transactions++
			return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
		},
		reader,
		selection,
		nil,
	)
	if err != nil {
		t.Fatal(err)
	}
	if transactions != 1 || reader.recordBulkCalls != 1 || base.recordTypeCalls != 0 {
		t.Fatalf(
			"combined reads = transactions:%d bulk:%d perObject:%d",
			transactions, reader.recordBulkCalls, base.recordTypeCalls,
		)
	}
	snapshotArtifact, err := catalogsnapshot.CompileEffectiveMetadata(effective)
	if err != nil {
		t.Fatal(err)
	}
	snapshot, err := catalogsnapshot.OpenCatalogSnapshot(snapshotArtifact)
	if err != nil {
		t.Fatal(err)
	}
	mutationArtifact, err := catalogsnapshot.ProjectRuntimeMetadataView(
		snapshot,
		catalogsnapshot.ProjectionKey{
			AppInstallationID: selection.AppInstallationID,
			CapabilityID:      recordmutationv1.CapabilityName,
		},
	)
	if err != nil {
		t.Fatal(err)
	}
	permissionArtifact, err := catalogsnapshot.ProjectRuntimeMetadataView(
		snapshot,
		catalogsnapshot.ProjectionKey{
			AppInstallationID: selection.AppInstallationID,
			CapabilityID:      effectivepermissionsv1.CapabilityName,
		},
	)
	if err != nil {
		t.Fatal(err)
	}
	mutationView, err := catalogsnapshot.OpenRuntimeMetadataView(mutationArtifact)
	if err != nil {
		t.Fatal(err)
	}
	permissionView, err := catalogsnapshot.OpenRuntimeMetadataView(permissionArtifact)
	if err != nil {
		t.Fatal(err)
	}
	permissionObject, ok := permissionView.EffectivePermissionObject("WorkItem")
	mutationRecordTypes := mutationView.RecordTypesForObject("WorkItem")
	if !ok || mutationView.SourceSnapshotDigest() != permissionView.SourceSnapshotDigest() ||
		mutationView.Lineage() != permissionView.Lineage() || mutationView.Lineage().CatalogRevision != 7 ||
		len(mutationRecordTypes) != 1 || mutationRecordTypes[0].ID != "rt-active" ||
		len(permissionObject.RecordTypes) != 1 || permissionObject.RecordTypes[0].RecordTypeID != "rt-active" {
		t.Fatalf(
			"combined record-type authority = mutation:%#v permission:%#v found:%t",
			mutationRecordTypes, permissionObject, ok,
		)
	}
}

func TestReadEffectiveMetadataBindsMutationFactsWithoutProductRoutePolicy(t *testing.T) {
	reader := &markedReader{
		t: t, objects: []*models.ObjectMetadata{validObject(constants.TableConnectedApp)},
		validationRules: []*models.ValidationRule{{
			ID: "validation-connected-app", ObjectAPIName: constants.TableConnectedApp,
			Name: "RequireName", Active: true, Condition: "Name = ''", ErrorMessage: "name required",
		}},
	}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityID: "runtime.records.mutate.v1",
		CatalogRevision:     7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	effective, err := ReadEffectiveMetadata(context.Background(), func(ctx context.Context, fn func(context.Context) error) error {
		return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
	}, reader, selection, nil)
	if err != nil {
		t.Fatal(err)
	}
	var document struct {
		Definitions []json.RawMessage `json:"definitions"`
		Projections []struct {
			DefinitionComponentIDs []string `json:"definitionComponentIds"`
		} `json:"runtimeProjections"`
		Mutation struct {
			ValidationRules []json.RawMessage `json:"validationRules"`
		} `json:"mutation"`
	}
	if err := json.Unmarshal(effective.Bytes(), &document); err != nil {
		t.Fatal(err)
	}
	if len(document.Mutation.ValidationRules) != 1 {
		t.Fatalf("effective mutation closure = %#v", document.Mutation)
	}
	if len(document.Definitions) != 0 || len(document.Projections) != 1 ||
		len(document.Projections[0].DefinitionComponentIDs) != 0 {
		t.Fatalf("effective mutation facts manufactured App definition lineage: definitions=%#v projections=%#v",
			document.Definitions, document.Projections)
	}
}

func TestReadEffectiveMetadataProjectsMutationRelationshipsAndGuardsInOneTransaction(t *testing.T) {
	source := validObject("Source")
	source.Fields = append(source.Fields, models.FieldMetadata{
		ID: "field-source-name", APIName: "Name", Type: constants.FieldTypeString, PhysicalName: "name",
	})
	target := validObject("Target")
	relationshipName := "Source"
	target.Fields = append(target.Fields,
		models.FieldMetadata{ID: "field-target-source", APIName: "SourceId", Type: constants.FieldTypeReference, ReferenceTo: []string{"Source"}, RelationshipName: &relationshipName, PhysicalName: "source_id"},
		models.FieldMetadata{ID: "field-target-subject", APIName: "Subject", Type: constants.FieldTypeString, PhysicalName: "subject"},
	)
	reader := &markedReader{
		t: t, objects: []*models.ObjectMetadata{target, source},
		fieldMappings: []catalogsnapshot.FieldMappingRule{{
			SourceObject: "Source", TargetObject: "Target", ActionType: "createTarget",
			SourceField: "Name", TargetField: "Subject", SourceLookupField: "SourceId",
		}},
		guardEntries: map[string][]recordsguard.CreateFromSourceGuardEntry{
			"Target": {{SourceFKField: "SourceId", OwningStandardActionId: "action-create-target", ActionName: "CreateTargetFromSource"}},
		},
	}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityIDs: []string{"runtime.records.evaluate-access.v1", "runtime.records.mutate.v1"},
		CatalogRevision:      7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	effective, err := ReadEffectiveMetadata(context.Background(), func(ctx context.Context, fn func(context.Context) error) error {
		return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
	}, reader, selection, nil)
	if err != nil {
		t.Fatal(err)
	}
	var document struct {
		Relationships []struct {
			ChildObjectAPIName  string `json:"childObjectApiName"`
			ParentObjectAPIName string `json:"parentObjectApiName"`
		} `json:"relationships"`
		Mutation struct {
			Guards []catalogsnapshot.CreateFromSourceGuardRule `json:"createSourceGuards"`
		} `json:"mutation"`
	}
	if err := json.Unmarshal(effective.Bytes(), &document); err != nil {
		t.Fatal(err)
	}
	if len(document.Relationships) != 1 || document.Relationships[0].ChildObjectAPIName != "Target" ||
		document.Relationships[0].ParentObjectAPIName != "Source" {
		t.Fatalf("mutation relationship closure = %#v", document.Relationships)
	}
	if len(document.Mutation.Guards) != 1 || document.Mutation.Guards[0].TargetObject != "Target" ||
		document.Mutation.Guards[0].OwningStandardActionID != "action-create-target" {
		t.Fatalf("mutation guard closure = %#v", document.Mutation.Guards)
	}
}

func TestReadEffectiveMetadataFailsClosedOnBrokenMutationFlowClosure(t *testing.T) {
	reader := &markedReader{
		t: t, objects: []*models.ObjectMetadata{validObject("WorkItem")},
		flowDefinitions: []*models.FlowDefinition{{
			Id: "definition-active", DeveloperName: "NormalizeWorkItem", ProcessType: "AutoLaunchedFlow", ActiveVersionId: "missing-version",
		}},
		flowVersions: map[string][]*models.FlowVersion{"definition-active": {}},
	}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityID: "runtime.records.mutate.v1",
		CatalogRevision:     7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	_, err := ReadEffectiveMetadata(context.Background(), func(ctx context.Context, fn func(context.Context) error) error {
		return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
	}, reader, selection, nil)
	if err == nil || !strings.Contains(err.Error(), `references absent active version "missing-version"`) {
		t.Fatalf("broken active Flow pointer error = %v", err)
	}
}

func TestReadEffectiveMetadataPublishesManualFlowClosureForFlowCapability(t *testing.T) {
	reader := &markedReader{
		t: t, objects: []*models.ObjectMetadata{validObject("WorkItem")},
		flowDefinitions: []*models.FlowDefinition{{
			Id: "definition-manual", DeveloperName: "ManualAction",
			ProcessType: "AutoLaunchedFlow", ActiveVersionId: "version-manual",
			IsCustomized: true, OwnerPack: "workflow-pack",
		}},
		flowVersions: map[string][]*models.FlowVersion{
			"definition-manual": {{
				Id: "version-manual", DefinitionId: "definition-manual",
				VersionNumber: 1, Status: models.FlowStatusActive,
				ProcessType: "AutoLaunchedFlow", Source: "standard",
				MetadataRaw: []byte(`{"status":"Active","runAtomically":true,"start":{},"assignments":[{"name":"Done","locationX":0,"locationY":0}]}`),
			}},
		},
	}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityIDs: []string{
			queryv1.CapabilityName,
			flowv1.CapabilityName,
		},
		CatalogRevision: 7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	effective, err := ReadEffectiveMetadata(
		context.Background(),
		func(ctx context.Context, fn func(context.Context) error) error {
			return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
		},
		reader,
		selection,
		nil,
	)
	if err != nil {
		t.Fatal(err)
	}
	var document struct {
		Projections []struct {
			CapabilityID string `json:"capabilityId"`
			Profile      string `json:"profile"`
		} `json:"runtimeProjections"`
		Mutation struct {
			FlowDefinitions []struct {
				DeveloperName string `json:"developerName"`
				ActiveVersion string `json:"activeVersionId"`
			} `json:"flowDefinitions"`
			FlowVersions []struct {
				ID string `json:"id"`
			} `json:"flowVersions"`
		} `json:"mutation"`
	}
	if err := json.Unmarshal(effective.Bytes(), &document); err != nil {
		t.Fatal(err)
	}
	if len(document.Mutation.FlowDefinitions) != 1 ||
		document.Mutation.FlowDefinitions[0].DeveloperName != "ManualAction" ||
		document.Mutation.FlowDefinitions[0].ActiveVersion != "version-manual" ||
		len(document.Mutation.FlowVersions) != 1 ||
		document.Mutation.FlowVersions[0].ID != "version-manual" {
		t.Fatalf("manual Flow publication = %#v", document.Mutation)
	}
	found := false
	for _, projection := range document.Projections {
		if projection.CapabilityID == flowv1.CapabilityName {
			found = projection.Profile == string(catalogsnapshot.ProjectionRecordMutationV1)
		}
	}
	if !found {
		t.Fatalf("Flow capability projection = %#v", document.Projections)
	}
	snapshotArtifact, err := catalogsnapshot.CompileEffectiveMetadata(effective)
	if err != nil {
		t.Fatal(err)
	}
	snapshot, err := catalogsnapshot.OpenCatalogSnapshot(snapshotArtifact)
	if err != nil {
		t.Fatal(err)
	}
	viewArtifact, err := catalogsnapshot.ProjectRuntimeMetadataView(
		snapshot,
		catalogsnapshot.ProjectionKey{
			AppInstallationID: selection.AppInstallationID,
			CapabilityID:      flowv1.CapabilityName,
		},
	)
	if err != nil {
		t.Fatal(err)
	}
	view, err := catalogsnapshot.OpenRuntimeMetadataView(viewArtifact)
	if err != nil {
		t.Fatal(err)
	}
	version, ok := view.ActiveFlowVersion("ManualAction")
	if !ok || version == nil || version.Id != "version-manual" ||
		version.VersionNumber != 1 || !version.DefinitionIsCustomized ||
		version.DefinitionOwnerPack != "workflow-pack" {
		t.Fatalf("projected exact manual Flow = %#v, %v", version, ok)
	}
}

func TestReadEffectiveMetadataUsesOneTransactionAndIsDeterministic(t *testing.T) {
	reader := &markedReader{t: t, objects: []*models.ObjectMetadata{validObject("Beta"), validObject("Alpha")}}
	transactions := 0
	run := func(ctx context.Context, fn func(context.Context) error) error {
		transactions++
		return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
	}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityID: "runtime.records.evaluate-access.v1",
		CatalogRevision:     7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	first, err := ReadEffectiveMetadata(context.Background(), run, reader, selection, nil)
	if err != nil {
		t.Fatalf("read effective metadata: %v", err)
	}
	reader.objects[0], reader.objects[1] = reader.objects[1], reader.objects[0]
	second, err := ReadEffectiveMetadata(context.Background(), run, reader, selection, nil)
	if err != nil {
		t.Fatalf("read reordered effective metadata: %v", err)
	}
	if first.Digest() != second.Digest() || string(first.Bytes()) != string(second.Bytes()) {
		t.Fatal("repository ordering changed canonical effective metadata")
	}
	if transactions != 2 || reader.sharingCalls != 4 {
		t.Fatalf("transactions = %d, sharing calls = %d", transactions, reader.sharingCalls)
	}
}

func TestReadEffectiveMetadataPublishesDerivedFieldProvenanceToMutationView(t *testing.T) {
	previous := fieldprovenance.Default()
	t.Cleanup(func() { fieldprovenance.SetDefault(previous) })
	fieldprovenance.SetDefault(fieldprovenance.BuildClassifier(
		nil,
		[]fieldprovenance.ObjectDeclaration{{
			APIName: "Lead",
			Fields: []fieldprovenance.FieldDeclaration{{
				APIName: "HubSpot_Id__c",
			}},
		}},
		nil,
		nil,
	))

	lead := validObject("Lead")
	lead.Fields = append(lead.Fields, models.FieldMetadata{
		ID: "field-lead-hubspot-id", APIName: "HubSpot_Id__c", Label: "HubSpot ID",
		Type: constants.FieldTypeString, PhysicalName: "HubSpot_Id__c",
		Createable: true, Updateable: true,
	})
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityID: recordmutationv1.CapabilityName,
		CatalogRevision:     7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	effective, err := ReadEffectiveMetadata(
		context.Background(),
		func(ctx context.Context, fn func(context.Context) error) error {
			return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
		},
		&markedReader{t: t, objects: []*models.ObjectMetadata{lead}},
		selection,
		nil,
	)
	if err != nil {
		t.Fatal(err)
	}
	snapshotArtifact, err := catalogsnapshot.CompileEffectiveMetadata(effective)
	if err != nil {
		t.Fatal(err)
	}
	snapshot, err := catalogsnapshot.OpenCatalogSnapshot(snapshotArtifact)
	if err != nil {
		t.Fatal(err)
	}
	viewArtifact, err := catalogsnapshot.ProjectRuntimeMetadataView(
		snapshot,
		catalogsnapshot.ProjectionKey{
			AppInstallationID: selection.AppInstallationID,
			CapabilityID:      recordmutationv1.CapabilityName,
		},
	)
	if err != nil {
		t.Fatal(err)
	}
	view, err := catalogsnapshot.OpenRuntimeMetadataView(viewArtifact)
	if err != nil {
		t.Fatal(err)
	}
	projectedLead, ok := view.Object("Lead")
	if !ok {
		t.Fatal("mutation view is missing Lead")
	}
	projected := models.FindField(projectedLead, "HubSpot_Id__c")
	if projected == nil || projected.Source != constants.FieldSourceStandardSpec {
		t.Fatalf("projected Lead.HubSpot_Id__c source = %#v, want %q", projected, constants.FieldSourceStandardSpec)
	}
	if source := models.FindField(lead, "HubSpot_Id__c"); source == nil || source.Source != "" {
		t.Fatalf("Catalog provenance publication mutated repository metadata: %#v", source)
	}
}

func TestReadEffectiveMetadataDerivesMasterDetailSharingParent(t *testing.T) {
	parent := validObject("Parent")
	child := validObject("Child")
	child.SharingModel = constants.SharingModelControlledByParent
	child.Fields = append(child.Fields, models.FieldMetadata{
		ID: "field-child-parent", APIName: "Parent__c", Label: "Parent",
		Type: constants.FieldTypeMasterDetail, PhysicalName: "parent_id",
		ReferenceTo: []string{"Parent"},
	})
	reader := &markedReader{t: t, objects: []*models.ObjectMetadata{child, parent}}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityID: "runtime.records.evaluate-access.v1",
		CatalogRevision:     7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	effective, err := ReadEffectiveMetadata(context.Background(), func(ctx context.Context, fn func(context.Context) error) error {
		return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
	}, reader, selection, nil)
	if err != nil {
		t.Fatalf("field-derived master-detail relationship was not compiled: %v", err)
	}
	var document struct {
		Relationships []struct {
			ChildObjectAPIName  string `json:"childObjectApiName"`
			ParentObjectAPIName string `json:"parentObjectApiName"`
			FieldAPIName        string `json:"fieldApiName"`
			RelationshipType    string `json:"relationshipType"`
			IsSharingParent     bool   `json:"isSharingParent"`
			CascadeDelete       bool   `json:"cascadeDelete"`
		} `json:"relationships"`
	}
	if err := json.Unmarshal(effective.Bytes(), &document); err != nil {
		t.Fatalf("decode effective metadata: %v", err)
	}
	if len(document.Relationships) != 1 {
		t.Fatalf("effective relationships = %#v, want one field-derived edge", document.Relationships)
	}
	relationship := document.Relationships[0]
	if relationship.ChildObjectAPIName != "Child" ||
		relationship.ParentObjectAPIName != "Parent" ||
		relationship.FieldAPIName != "Parent__c" ||
		relationship.RelationshipType != string(constants.FieldTypeMasterDetail) ||
		!relationship.IsSharingParent || !relationship.CascadeDelete {
		t.Fatalf("effective relationship = %#v", relationship)
	}
}

func TestReadEffectiveMetadataDoesNotPromoteFieldOnlyLookupToAbsentTargetForQuery(t *testing.T) {
	account := validObject("Account")
	account.Fields = append(account.Fields, models.FieldMetadata{
		ID: "field-account-optional-package", APIName: "package__Profile__c", Label: "Package Profile",
		Type: constants.FieldTypeReference, PhysicalName: "package_profile_id",
		ReferenceTo: []string{"package__Profile__c"},
	})

	reader := &markedReader{t: t, objects: []*models.ObjectMetadata{account}}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityIDs: []string{"runtime.records.evaluate-access.v1", "runtime.records.query.v1"},
		CatalogRevision:      7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	effective, err := ReadEffectiveMetadata(context.Background(), func(ctx context.Context, fn func(context.Context) error) error {
		return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
	}, reader, selection, nil)
	if err != nil {
		t.Fatalf("field-only optional lookup changed the query closure: %v", err)
	}
	var document struct {
		Relationships []json.RawMessage `json:"relationships"`
	}
	if err := json.Unmarshal(effective.Bytes(), &document); err != nil {
		t.Fatalf("decode effective metadata: %v", err)
	}
	if len(document.Relationships) != 0 {
		t.Fatalf("field-only optional lookup produced Catalog relationships: %s", effective.Bytes())
	}
	field := models.FindField(account, "package__Profile__c")
	if field == nil || field.Type != constants.FieldTypeReference ||
		len(field.ReferenceTo) != 1 || field.ReferenceTo[0] != "package__Profile__c" {
		t.Fatalf("source field metadata was rewritten: %#v", field)
	}
}

func TestReadEffectiveMetadataStillValidatesFieldDerivedSharingParentToAbsentTarget(t *testing.T) {
	child := validObject("Child")
	child.SharingModel = constants.SharingModelControlledByParent
	child.Fields = append(child.Fields, models.FieldMetadata{
		ID: "field-child-missing-parent", APIName: "Parent__c", Label: "Parent",
		Type: constants.FieldTypeMasterDetail, PhysicalName: "parent_id",
		ReferenceTo: []string{"MissingParent__c"},
	})

	if _, err := readTestEffectiveMetadata(t, &markedReader{t: t, objects: []*models.ObjectMetadata{child}}); err == nil ||
		!strings.Contains(err.Error(), `parent object "MissingParent__c" is absent`) {
		t.Fatalf("field-derived sharing-parent error = %v", err)
	}
}

func TestReadEffectiveMetadataStillValidatesMalformedFieldDerivedTarget(t *testing.T) {
	account := validObject("Account")
	account.Fields = append(account.Fields, models.FieldMetadata{
		ID: "field-account-malformed-package", APIName: "PackageProfile__c", Label: "Package Profile",
		Type: constants.FieldTypeReference, PhysicalName: "package_profile_id",
		ReferenceTo: []string{" package__Profile__c"},
	})
	reader := &markedReader{t: t, objects: []*models.ObjectMetadata{account}}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityIDs: []string{"runtime.records.evaluate-access.v1", "runtime.records.query.v1"},
		CatalogRevision:      7, SchemaGeneration: 8, EngineGeneration: 9,
	}

	_, err := ReadEffectiveMetadata(context.Background(), func(ctx context.Context, fn func(context.Context) error) error {
		return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
	}, reader, selection, nil)
	if err == nil || !strings.Contains(err.Error(), "parentObjectApiName") {
		t.Fatalf("malformed field-derived target error = %v", err)
	}
}

func TestReadEffectiveMetadataIncludesFieldOwnedLookupForQueryCapability(t *testing.T) {
	for _, runtimeCapabilityID := range []string{queryv1.CapabilityName, recyclebinv1.CapabilityName, relatedcountsv1.CapabilityName} {
		t.Run(runtimeCapabilityID, func(t *testing.T) {
			parent := validObject("Project")
			child := validObject("Issue")
			relationshipName := "Project"
			child.Fields = append(child.Fields, models.FieldMetadata{
				ID: "field-issue-project", APIName: "ProjectId", Label: "Project",
				Type: constants.FieldTypeReference, PhysicalName: "project_id",
				ReferenceTo: []string{"Project"}, RelationshipName: &relationshipName,
			})
			reader := &markedReader{t: t, objects: []*models.ObjectMetadata{child, parent}}
			selection := MetadataSelection{
				OrgID: "org-test", AppInstallationID: "installation-test",
				RuntimeCapabilityIDs: []string{"runtime.records.evaluate-access.v1", runtimeCapabilityID},
				CatalogRevision:      7, SchemaGeneration: 8, EngineGeneration: 9,
			}
			effective, err := ReadEffectiveMetadata(context.Background(), func(ctx context.Context, fn func(context.Context) error) error {
				return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
			}, reader, selection, nil)
			if err != nil {
				t.Fatal(err)
			}
			var document struct {
				Relationships []struct {
					ChildObjectAPIName  string `json:"childObjectApiName"`
					ParentObjectAPIName string `json:"parentObjectApiName"`
					FieldAPIName        string `json:"fieldApiName"`
					RelationshipName    string `json:"relationshipName"`
				} `json:"relationships"`
			}
			if err := json.Unmarshal(effective.Bytes(), &document); err != nil {
				t.Fatal(err)
			}
			if len(document.Relationships) != 1 || document.Relationships[0].ChildObjectAPIName != "Issue" ||
				document.Relationships[0].ParentObjectAPIName != "Project" || document.Relationships[0].FieldAPIName != "ProjectId" ||
				document.Relationships[0].RelationshipName != "Project" {
				t.Fatalf("query relationship closure = %#v", document.Relationships)
			}
		})
	}
}

func TestReadEffectiveMetadataPublishesPlatformUserNameToRecordQueryView(t *testing.T) {
	user := validObject(constants.TableUser)
	user.Fields = append(user.Fields,
		models.FieldMetadata{
			ID: "field-user-first-name", APIName: constants.FieldFirstName, Label: "First Name",
			Type: constants.FieldTypeString, PhysicalName: "first_name",
		},
		models.FieldMetadata{
			ID: "field-user-last-name", APIName: constants.FieldLastName, Label: "Last Name",
			Type: constants.FieldTypeString, PhysicalName: "last_name",
		},
	)
	reader := &markedReader{t: t, objects: []*models.ObjectMetadata{user}}
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityIDs: []string{"runtime.records.evaluate-access.v1", queryv1.CapabilityName},
		CatalogRevision:      7, SchemaGeneration: 8, EngineGeneration: 9,
	}

	effective, err := ReadEffectiveMetadata(context.Background(), func(ctx context.Context, fn func(context.Context) error) error {
		return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
	}, reader, selection, nil)
	if err != nil {
		t.Fatal(err)
	}
	snapshotArtifact, err := catalogsnapshot.CompileEffectiveMetadata(effective)
	if err != nil {
		t.Fatal(err)
	}
	snapshot, err := catalogsnapshot.OpenCatalogSnapshot(snapshotArtifact)
	if err != nil {
		t.Fatal(err)
	}
	viewArtifact, err := catalogsnapshot.ProjectRuntimeMetadataView(snapshot, catalogsnapshot.ProjectionKey{
		AppInstallationID: selection.AppInstallationID,
		CapabilityID:      queryv1.CapabilityName,
	})
	if err != nil {
		t.Fatal(err)
	}
	view, err := catalogsnapshot.OpenRuntimeMetadataView(viewArtifact)
	if err != nil {
		t.Fatal(err)
	}
	projectedUser, ok := view.Object(constants.TableUser)
	if !ok {
		t.Fatal("record-query view has no User object")
	}
	name := models.FindField(projectedUser, constants.FieldName)
	if name == nil || !name.IsCompound || !name.IsVirtual ||
		name.VirtualKind != constants.VirtualFieldCompound || name.Createable || name.Updateable ||
		len(name.ComposedFrom) != 2 || name.ComposedFrom[0] != constants.FieldFirstName ||
		name.ComposedFrom[1] != constants.FieldLastName {
		t.Fatalf("record-query User.Name = %#v", name)
	}
}

func TestReadEffectiveMetadataStillValidatesExplicitLookupToAbsentTarget(t *testing.T) {
	account := validObject("Account")
	account.Fields = append(account.Fields, models.FieldMetadata{
		ID: "field-account-explicit-package", APIName: "package__Profile__c", Label: "Package Profile",
		Type: constants.FieldTypeReference, PhysicalName: "package_profile_id",
		ReferenceTo: []string{"package__Profile__c"},
	})
	reader := &markedReader{
		t: t, objects: []*models.ObjectMetadata{account},
		relationships: []*models.Relationship{{
			ChildObjectAPIName: "Account", ParentObjectAPIName: "package__Profile__c",
			FieldAPIName: "package__Profile__c",
		}},
	}

	if _, err := readTestEffectiveMetadata(t, reader); err == nil ||
		!strings.Contains(err.Error(), `parent object "package__Profile__c" is absent`) {
		t.Fatalf("explicit dangling relationship error = %v", err)
	}
}

func TestReadEffectiveMetadataRejectsDuplicateRelationshipOverlays(t *testing.T) {
	parent := validObject("Parent")
	child := validObject("Child")
	child.Fields = append(child.Fields, models.FieldMetadata{
		ID: "field-child-parent", APIName: "Parent__c", Label: "Parent",
		Type: constants.FieldTypeReference, PhysicalName: "parent_id",
		ReferenceTo: []string{"Parent"},
	})
	reader := &markedReader{
		t: t, objects: []*models.ObjectMetadata{child, parent},
		relationships: []*models.Relationship{
			{ChildObjectAPIName: "Child", ParentObjectAPIName: "Parent", FieldAPIName: "Parent__c", CascadeDelete: true},
			{ChildObjectAPIName: "child", ParentObjectAPIName: "parent", FieldAPIName: "parent__c", RestrictedDelete: true},
		},
	}
	_, err := readTestEffectiveMetadata(t, reader)
	if err == nil || !strings.Contains(err.Error(), "duplicate explicit relationship overlay") {
		t.Fatalf("duplicate overlay error = %v", err)
	}
}

func TestReadEffectiveMetadataRejectsStaleAndRetargetedRelationshipOverlays(t *testing.T) {
	child := validObject("Child")
	child.Fields = append(child.Fields, models.FieldMetadata{
		ID: "field-child-parent", APIName: "Parent__c", Label: "Parent",
		Type: constants.FieldTypeReference, PhysicalName: "parent_id",
		ReferenceTo: []string{"ActualParent"},
	})
	for name, relationship := range map[string]*models.Relationship{
		"missing field": {
			ChildObjectAPIName: "Child", ParentObjectAPIName: "ActualParent", FieldAPIName: "Missing__c",
		},
		"retargeted parent": {
			ChildObjectAPIName: "Child", ParentObjectAPIName: "StaleParent", FieldAPIName: "Parent__c",
		},
	} {
		t.Run(name, func(t *testing.T) {
			reader := &markedReader{
				t: t,
				objects: []*models.ObjectMetadata{
					child, validObject("ActualParent"), validObject("StaleParent"),
				},
				relationships: []*models.Relationship{relationship},
			}
			if _, err := readTestEffectiveMetadata(t, reader); err == nil || !strings.Contains(err.Error(), "has no field-owned edge") {
				t.Fatalf("stale relationship error = %v", err)
			}
		})
	}
}

func TestReadEffectiveMetadataPreservesUnknownChildForCompilerRejection(t *testing.T) {
	reader := &markedReader{
		t: t, objects: []*models.ObjectMetadata{validObject("Parent")},
		relationships: []*models.Relationship{{
			ChildObjectAPIName: "MissingChild", ParentObjectAPIName: "Parent", FieldAPIName: "Parent__c",
		}},
	}
	if _, err := readTestEffectiveMetadata(t, reader); err == nil || !strings.Contains(err.Error(), "compile effective metadata") {
		t.Fatalf("unknown-child relationship error = %v", err)
	}
}

func readTestEffectiveMetadata(t *testing.T, reader *markedReader) (catalogsnapshot.EffectiveMetadata, error) {
	t.Helper()
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityID: "runtime.records.evaluate-access.v1",
		CatalogRevision:     7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	return ReadEffectiveMetadata(context.Background(), func(ctx context.Context, fn func(context.Context) error) error {
		return fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot"))
	}, reader, selection, nil)
}

func TestReadEffectiveMetadataFailsClosedWithoutCompleteTransaction(t *testing.T) {
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityID: "runtime.records.evaluate-access.v1",
		CatalogRevision:     7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	reader := &markedReader{t: t, objects: []*models.ObjectMetadata{validObject("WorkItem")}}
	if _, err := ReadEffectiveMetadata(context.Background(), nil, reader, selection, nil); err == nil {
		t.Fatal("nil transaction runner was accepted")
	}
	rollback := errors.New("forced rollback")
	_, err := ReadEffectiveMetadata(context.Background(), func(ctx context.Context, fn func(context.Context) error) error {
		if err := fn(context.WithValue(ctx, transactionMarker{}, "one-snapshot")); err != nil {
			return err
		}
		return rollback
	}, reader, selection, nil)
	if !errors.Is(err, rollback) {
		t.Fatalf("transaction failure = %v, want forced rollback", err)
	}
}

func TestReadEffectiveMetadataRejectsUnsupportedProjectionBeforeRepositoryAccess(t *testing.T) {
	selection := MetadataSelection{
		OrgID: "org-test", AppInstallationID: "installation-test",
		RuntimeCapabilityID: "runtime.records.other.v1",
		CatalogRevision:     7, SchemaGeneration: 8, EngineGeneration: 9,
	}
	transactionCalled := false
	_, err := ReadEffectiveMetadata(context.Background(), func(context.Context, func(context.Context) error) error {
		transactionCalled = true
		return nil
	}, &markedReader{t: t}, selection, nil)
	if err == nil || transactionCalled {
		t.Fatalf("unsupported projection error = %v, transaction called = %v", err, transactionCalled)
	}
}

func validObject(name string) *models.ObjectMetadata {
	return &models.ObjectMetadata{
		ID: "object-" + name, APIName: name, Label: name, PluralLabel: name + "s",
		SharingModel: constants.SharingModelPublicReadWrite,
		Fields: []models.FieldMetadata{{
			ID: "field-" + name + "-id", APIName: "Id", Label: "ID",
			Type: constants.FieldTypeString, PhysicalName: "id",
		}},
	}
}

func TestWorkloadNavigationCannotSelectCatalogProjection(t *testing.T) {
	if _, err := projectionProfile("runtime.application-navigation.v1"); err == nil {
		t.Fatal("current navigation configuration must not acquire a Catalog serving projection")
	}
}

func (r *markedReader) GetRuntimeSearchScopeOrder(ctx context.Context) ([]metadata.SearchScopeOrderItem, error) {
	r.requireTransaction(ctx)
	return r.searchScope, nil
}
