package metadata

import (
	"context"
	"strings"
	"testing"

	"github.com/nexuscrm/metadata/catalogsnapshot"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/approvalir"
	approvalv1 "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/approvalv1"
	flowsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/flowv1"
)

func TestRuntimeMetadataServiceUsesOnlyRequestBoundImmutableView(t *testing.T) {
	view := runtimeMetadataServiceView(t)
	type contextKey struct{}
	service, err := NewRuntimeMetadataService(func(ctx context.Context) (*catalogsnapshot.RuntimeMetadataView, bool) {
		bound, ok := ctx.Value(contextKey{}).(*catalogsnapshot.RuntimeMetadataView)
		return bound, ok && bound != nil
	})
	if err != nil {
		t.Fatal(err)
	}

	if service.GetSchema(context.Background(), "Widget") != nil ||
		len(service.GetSchemas(context.Background())) != 0 ||
		len(service.GetRelationships(context.Background(), "Widget")) != 0 ||
		len(service.GetSharingRules(context.Background(), "Widget")) != 0 ||
		service.GetField("Widget", "Id") != nil {
		t.Fatal("request-bound metadata service exposed a global or repository fallback")
	}
	if _, ok := service.ResolveObjectForKeyPrefix(context.Background(), "0WD"); ok {
		t.Fatal("unbound request resolved key-prefix identity")
	}
	if _, ok := service.KeyPrefixForObject(context.Background(), "Widget"); ok {
		t.Fatal("unbound request resolved object key prefix")
	}
	if _, ok := service.CanonicalObjectAPIName(context.Background(), "widget"); ok {
		t.Fatal("unbound request resolved canonical object identity")
	}
	if err := service.RefreshCache(t.Context()); err == nil {
		t.Fatal("request-bound metadata service accepted process-global refresh")
	}

	ctx := context.WithValue(t.Context(), contextKey{}, view)
	schema := service.GetSchema(ctx, "widget")
	if schema == nil || schema.APIName != "Widget" || len(service.GetSchemas(ctx)) != 1 {
		t.Fatalf("bound schema = %#v schemas=%#v", schema, service.GetSchemas(ctx))
	}
	if !view.SupportsRecordAccessServing() {
		t.Fatal("current record-access view is not serving eligible")
	}
	if object, ok := service.ResolveObjectForRecordID(ctx, "0WD000000000001"); !ok || object != "Widget" {
		t.Fatalf("record-access ResolveObjectForRecordID = %q, %v", object, ok)
	}
}

func TestRuntimeMetadataServiceCachesDetachedSchemaOnlyWithinOneRequest(t *testing.T) {
	view := runtimeMetadataServiceView(t)
	service, err := NewRuntimeMetadataService(RuntimeMetadataViewFromContext)
	if err != nil {
		t.Fatal(err)
	}

	ctx := WithRuntimeMetadataReadCache(WithRuntimeMetadataView(t.Context(), view))
	first := service.GetSchema(ctx, "Widget")
	second := service.GetSchema(ctx, "widget")
	if first == nil || second != first {
		t.Fatalf("request-local schema reuse = first %#v second %#v", first, second)
	}
	first.APIName = "mutated-only-in-this-request"
	if got := service.GetSchema(ctx, "Widget"); got != first || got.APIName != first.APIName {
		t.Fatalf("request-local schema cache did not retain its detached materialization: %#v", got)
	}

	freshCtx := WithRuntimeMetadataReadCache(WithRuntimeMetadataView(t.Context(), view))
	fresh := service.GetSchema(freshCtx, "Widget")
	if fresh == nil || fresh == first || fresh.APIName != "Widget" {
		t.Fatalf("fresh request observed another request's detached mutation: %#v", fresh)
	}
	missingFirst := service.GetSchema(ctx, "Missing")
	missingSecond := service.GetSchema(ctx, "missing")
	if missingFirst != nil || missingSecond != nil {
		t.Fatalf("request-local missing schema result changed: %#v %#v", missingFirst, missingSecond)
	}
	if spaced := service.GetSchema(ctx, " Widget"); spaced != nil {
		t.Fatalf("invalid spaced identity resolved from cache: %#v", spaced)
	}
	if valid := service.GetSchema(ctx, "Widget"); valid != first {
		t.Fatalf("invalid spaced identity poisoned valid cached identity: %#v", valid)
	}
}

func TestRuntimeMetadataServiceExposesEffectivePermissionDecisionClosure(t *testing.T) {
	view := runtimeEffectivePermissionMetadataServiceView(t)
	service, err := NewRuntimeMetadataService(RuntimeMetadataViewFromContext)
	if err != nil {
		t.Fatal(err)
	}
	ctx := WithRuntimeMetadataReadCache(WithRuntimeMetadataView(t.Context(), view))
	child := service.GetSchema(ctx, "Child")
	if child == nil || child.SharingModel != constants.SharingModelControlledByParent ||
		models.FindField(child, "ParentId") == nil || len(service.GetSchemas(ctx)) != 2 {
		t.Fatalf("effective-permission schemas = child %#v all %#v", child, service.GetSchemas(ctx))
	}
	parent := service.GetParentControlledObject(ctx, child)
	if parent != "Parent" {
		t.Fatalf("parent-controlled object = %q, want Parent", parent)
	}
	relationship := service.GetSharingParentRelationship(ctx, "Child")
	if relationship == nil || relationship.FieldAPIName != "ParentId" || !relationship.IsSharingParent {
		t.Fatalf("sharing-parent relationship = %#v", relationship)
	}
}

func TestRuntimeMetadataServiceResolvesMutationObjectIdentityOnlyFromBoundView(t *testing.T) {
	view := runtimeMutationMetadataServiceView(t)
	type contextKey struct{}
	service, err := NewRuntimeMetadataService(func(ctx context.Context) (*catalogsnapshot.RuntimeMetadataView, bool) {
		bound, ok := ctx.Value(contextKey{}).(*catalogsnapshot.RuntimeMetadataView)
		return bound, ok && bound != nil
	})
	if err != nil {
		t.Fatal(err)
	}
	if _, ok := service.ResolveObjectForKeyPrefix(t.Context(), "0WD"); ok {
		t.Fatal("unbound request resolved key-prefix identity")
	}

	ctx := context.WithValue(t.Context(), contextKey{}, view)
	if object, ok := service.ResolveObjectForKeyPrefix(ctx, "0WD"); !ok || object != "Widget" {
		t.Fatalf("ResolveObjectForKeyPrefix = %q, %v", object, ok)
	}
	if _, ok := service.ResolveObjectForKeyPrefix(ctx, "0wd"); ok {
		t.Fatal("key-prefix identity lookup lost case sensitivity")
	}
	if prefix, ok := service.KeyPrefixForObject(ctx, "widget"); !ok || prefix != "0WD" {
		t.Fatalf("KeyPrefixForObject = %q, %v", prefix, ok)
	}
	if object, ok := service.CanonicalObjectAPIName(ctx, "widget"); !ok || object != "Widget" {
		t.Fatalf("CanonicalObjectAPIName = %q, %v", object, ok)
	}
	if object, ok := service.ResolveObjectForRecordID(ctx, "0WD000000000001"); !ok || object != "Widget" {
		t.Fatalf("ResolveObjectForRecordID = %q, %v", object, ok)
	}
}

func TestRuntimeMetadataServiceDiscoversScheduledFlowsOnlyFromBoundView(t *testing.T) {
	view := runtimeScheduledFlowMetadataServiceView(t)
	type contextKey struct{}
	service, err := NewRuntimeMetadataService(func(ctx context.Context) (*catalogsnapshot.RuntimeMetadataView, bool) {
		bound, ok := ctx.Value(contextKey{}).(*catalogsnapshot.RuntimeMetadataView)
		return bound, ok && bound != nil
	})
	if err != nil {
		t.Fatal(err)
	}
	if definitions := service.GetScheduledFlowDefinitions(t.Context()); len(definitions) != 0 {
		t.Fatalf("unbound scheduled definitions = %#v", definitions)
	}
	if _, err := service.GetRuntimeScheduledFlowDefinitions(t.Context()); err == nil ||
		!strings.Contains(err.Error(), "view is required") {
		t.Fatalf("unbound Runtime scheduled discovery error = %v", err)
	}
	if definition := service.GetFlowDefinition(t.Context(), "flow-definition-scheduled"); definition != nil {
		t.Fatalf("unbound Flow definition = %#v", definition)
	}

	ctx := context.WithValue(t.Context(), contextKey{}, view)
	definitions := service.GetScheduledFlowDefinitions(ctx)
	if len(definitions) != 1 ||
		definitions[0].Id != "flow-definition-scheduled" ||
		definitions[0].ActiveVersionId != "flow-version-scheduled" {
		t.Fatalf("bound scheduled definitions = %#v", definitions)
	}
	definition := service.GetFlowDefinition(ctx, "flow-definition-scheduled")
	if definition == nil || definition.Id != definitions[0].Id {
		t.Fatalf("bound Flow definition = %#v", definition)
	}
	runtimeDefinitions, err := service.GetRuntimeScheduledFlowDefinitions(ctx)
	if err != nil || len(runtimeDefinitions) != 1 ||
		runtimeDefinitions[0].Id != definitions[0].Id {
		t.Fatalf("Runtime scheduled definitions = %#v, %v", runtimeDefinitions, err)
	}
}

func runtimeScheduledFlowMetadataServiceView(t *testing.T) *catalogsnapshot.RuntimeMetadataView {
	t.Helper()
	const installation = "installation-runtime-scheduled-metadata-test"
	keyPrefix := "0WD"
	snapshotArtifact, err := catalogsnapshot.CompileCatalogSnapshot(catalogsnapshot.CompileInput{
		OrgID:   "org-runtime-scheduled-metadata-test",
		Lineage: catalogsnapshot.Lineage{CatalogRevision: 2, SchemaGeneration: 1, EngineGeneration: 1},
		Objects: []catalogsnapshot.ObjectInput{{CatalogRevision: 2, Metadata: &models.ObjectMetadata{
			ID: "object-widget", APIName: "Widget", Label: "Widget", PluralLabel: "Widgets",
			SharingModel: constants.SharingModelPublicReadWrite, KeyPrefix: &keyPrefix,
			Fields: []models.FieldMetadata{{
				ID: "field-widget-id", APIName: constants.FieldID, Label: "ID",
				Type: constants.FieldTypeString, PhysicalName: constants.FieldID, IsSystem: true,
			}},
		}}},
		MutationDefinitions: []catalogsnapshot.MutationDefinitionInput{
			{CatalogRevision: 2, FlowDefinition: &models.FlowDefinition{
				Id: "flow-definition-scheduled", DeveloperName: "ScheduledWidget",
				ProcessType: "AutoLaunchedFlow", TriggerType: "Scheduled",
				TriggerObjectOrEvent: "Widget", ActiveVersionId: "flow-version-scheduled",
			}},
			{CatalogRevision: 2, FlowVersion: &models.FlowVersion{
				Id: "flow-version-scheduled", DefinitionId: "flow-definition-scheduled",
				VersionNumber: 1, Status: models.FlowStatusActive, ProcessType: "AutoLaunchedFlow",
				MetadataRaw: []byte(`{"start":{"object":"Widget","schedule":{"frequency":"Daily","startTime":"12:00:00","timezoneSidKey":"UTC"},"connector":{"targetReference":"Done"}},"assignments":[{"name":"Done"}]}`),
			}},
		},
		Projections: []catalogsnapshot.RuntimeProjectionInput{{
			CatalogRevision: 2, AppInstallationID: installation,
			CapabilityID: flowsemantic.CapabilityName,
			Profile:      catalogsnapshot.ProjectionRecordMutationV1,
			ObjectAPINames: []string{
				"Widget",
			},
		}},
	})
	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,
			CapabilityID:      flowsemantic.CapabilityName,
		},
	)
	if err != nil {
		t.Fatal(err)
	}
	view, err := catalogsnapshot.OpenRuntimeMetadataView(viewArtifact)
	if err != nil {
		t.Fatal(err)
	}
	return view
}

func TestRuntimeMetadataServiceResolvesQueryRelationshipsOnlyFromBoundView(t *testing.T) {
	view := runtimeQueryMetadataServiceView(t)
	type contextKey struct{}
	service, err := NewRuntimeMetadataService(func(ctx context.Context) (*catalogsnapshot.RuntimeMetadataView, bool) {
		bound, ok := ctx.Value(contextKey{}).(*catalogsnapshot.RuntimeMetadataView)
		return bound, ok && bound != nil
	})
	if err != nil {
		t.Fatal(err)
	}
	if _, ok := service.ForeignKeyForRelationship(context.Background(), "WorkItem", "Workspace"); ok {
		t.Fatal("unbound request resolved a relationship")
	}
	if targets, ok := service.TargetObjectsForForeignKey(context.Background(), "WorkItem", "WorkspaceId"); ok || len(targets) != 0 {
		t.Fatalf("unbound request targets=%#v, %v", targets, ok)
	}
	if children := service.GetChildRelationships(context.Background(), "Workspace"); len(children) != 0 {
		t.Fatalf("unbound request children=%#v", children)
	}

	ctx := context.WithValue(t.Context(), contextKey{}, view)
	if field, ok := service.ForeignKeyForRelationship(ctx, "workitem", "workspace"); !ok || field != "WorkspaceId" {
		t.Fatalf("foreign key=%q, %v", field, ok)
	}
	if targets, ok := service.TargetObjectsForForeignKey(ctx, "WorkItem", "workspaceid"); !ok || len(targets) != 1 || targets[0] != "Workspace" {
		t.Fatalf("targets=%#v, %v", targets, ok)
	}
	if children := service.GetChildRelationships(ctx, "workspace"); len(children) != 1 || children[0].APIName != "WorkItem" {
		t.Fatalf("children=%#v", children)
	}
}

func TestRuntimeMetadataServiceMutationValidationRulesFailClosedByProfile(t *testing.T) {
	mutationView := runtimeMutationMetadataServiceView(t)
	approvalExecutionView := runtimeApprovalMutationMetadataServiceView(t)
	readView := runtimeMetadataServiceView(t)
	type contextKey struct{}
	service, err := NewRuntimeMetadataService(func(ctx context.Context) (*catalogsnapshot.RuntimeMetadataView, bool) {
		bound, ok := ctx.Value(contextKey{}).(*catalogsnapshot.RuntimeMetadataView)
		return bound, ok && bound != nil
	})
	if err != nil {
		t.Fatal(err)
	}

	if _, err := service.GetValidationRulesForMutation(t.Context(), "Widget"); err == nil || !strings.Contains(err.Error(), "view is required") {
		t.Fatalf("unbound mutation validation-rule read error = %v", err)
	}
	if _, err := service.GetRecordTypes(t.Context(), "Widget"); err == nil || !strings.Contains(err.Error(), "view is required") {
		t.Fatalf("unbound record-type read error = %v", err)
	}
	readCtx := context.WithValue(t.Context(), contextKey{}, readView)
	if _, err := service.GetValidationRulesForMutation(readCtx, "Widget"); err == nil || !strings.Contains(err.Error(), "cannot provide record mutation validation rules") {
		t.Fatalf("read-profile mutation validation-rule read error = %v", err)
	}
	if _, err := service.GetRecordTypes(readCtx, "Widget"); err == nil || !strings.Contains(err.Error(), "cannot provide record-type mutation metadata") {
		t.Fatalf("read-profile record-type read error = %v", err)
	}
	if _, err := service.ListActiveTriggerSubscriptions(readCtx, "0WD", "RecordBeforeSave", "Create"); err == nil || !strings.Contains(err.Error(), "cannot provide record-trigger subscription metadata") {
		t.Fatalf("read-profile trigger-subscription read error = %v", err)
	}
	if _, err := service.GetRuntimeFlowDefinition(readCtx, "flow-definition-widget"); err == nil || !strings.Contains(err.Error(), "cannot provide Flow definition execution metadata") {
		t.Fatalf("read-profile Flow-definition read error = %v", err)
	}
	if _, err := service.GetRuntimeScheduledFlowDefinitions(readCtx); err == nil ||
		!strings.Contains(err.Error(), "cannot provide scheduled Flow discovery metadata") {
		t.Fatalf("read-profile scheduled-Flow discovery error = %v", err)
	}
	if _, err := service.GetFlowVersionsByIDs(readCtx, []string{"flow-version-widget"}); err == nil || !strings.Contains(err.Error(), "cannot provide Flow version execution metadata") {
		t.Fatalf("read-profile Flow-version read error = %v", err)
	}
	if _, err := service.GetRuntimeActiveFlowVersion(readCtx, "NormalizeWidget", nil); err == nil || !strings.Contains(err.Error(), "cannot provide active Flow execution metadata") {
		t.Fatalf("read-profile active-Flow read error = %v", err)
	}
	if !service.HasActiveRecordTriggeredFlow(readCtx, "Widget") {
		t.Fatal("wrong-profile trigger-presence read must fail safe")
	}
	mutationCtx := context.WithValue(t.Context(), contextKey{}, mutationView)
	if service.HasActiveRecordTriggeredFlowForEvent(mutationCtx, "Widget", "RecordAfterSave", "Create") {
		t.Fatal("mutation view without an exact after-save create subscriber reported one")
	}
	rules, err := service.GetValidationRulesForMutation(mutationCtx, "Widget")
	if err != nil {
		t.Fatal(err)
	}
	if len(rules) != 1 || rules[0].ID != "validation-widget" {
		t.Fatalf("mutation validation rules = %#v", rules)
	}
	recordTypes, err := service.GetRecordTypes(mutationCtx, "Widget")
	if err != nil {
		t.Fatal(err)
	}
	if len(recordTypes) != 1 || recordTypes[0].ID != "record-type-widget" {
		t.Fatalf("mutation record types = %#v", recordTypes)
	}
	approvalCtx := context.WithValue(t.Context(), contextKey{}, approvalExecutionView)
	approvalRules, err := service.GetValidationRulesForMutation(approvalCtx, "Widget")
	if err != nil || len(approvalRules) != 1 || approvalRules[0].ID != "validation-widget" {
		t.Fatalf("approval mutation validation rules = %#v, %v", approvalRules, err)
	}
	if subscriptions, err := service.ListActiveTriggerSubscriptions(
		approvalCtx, "0WD", "RecordBeforeSave", "Create",
	); err != nil || len(subscriptions) != 0 {
		t.Fatalf("approval trigger-subscription closure = %#v, %v", subscriptions, err)
	}
	if service.HasActiveRecordTriggeredFlow(approvalCtx, "Widget") {
		t.Fatal("approval execution view invented a record-trigger subscription")
	}
}

func runtimeMetadataServiceView(t *testing.T) *catalogsnapshot.RuntimeMetadataView {
	t.Helper()
	const (
		installation = "installation-runtime-metadata-test"
		capability   = "runtime.records.evaluate-access.v1"
	)
	keyPrefix := "0WD"
	snapshotArtifact, err := catalogsnapshot.CompileCatalogSnapshot(catalogsnapshot.CompileInput{
		OrgID: "org-runtime-metadata-test",
		Lineage: catalogsnapshot.Lineage{
			CatalogRevision: 1, SchemaGeneration: 1, EngineGeneration: 1,
		},
		Objects: []catalogsnapshot.ObjectInput{{CatalogRevision: 1, Metadata: &models.ObjectMetadata{
			ID: "object-widget", APIName: "Widget", Label: "Widget", PluralLabel: "Widgets",
			SharingModel: constants.SharingModelPublicReadWrite, KeyPrefix: &keyPrefix,
			Fields: []models.FieldMetadata{{
				ID: "field-widget-id", APIName: constants.FieldID, Label: "ID",
				Type: constants.FieldTypeString, PhysicalName: constants.FieldID, IsSystem: true,
			}},
		}}},
		Projections: []catalogsnapshot.RuntimeProjectionInput{{
			CatalogRevision: 1, AppInstallationID: installation, CapabilityID: capability,
			Profile: catalogsnapshot.ProjectionRecordAccessV1, ObjectAPINames: []string{"Widget"},
		}},
	})
	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, CapabilityID: capability,
	})
	if err != nil {
		t.Fatal(err)
	}
	view, err := catalogsnapshot.OpenRuntimeMetadataView(viewArtifact)
	if err != nil {
		t.Fatal(err)
	}
	return view
}

func runtimeEffectivePermissionMetadataServiceView(t *testing.T) *catalogsnapshot.RuntimeMetadataView {
	t.Helper()
	const (
		installation = "installation-runtime-effective-permission-test"
		capability   = "runtime.permissions.read-effective.v1"
	)
	parent := &models.ObjectMetadata{
		ID: "object-parent", APIName: "Parent", Label: "Parent", PluralLabel: "Parents",
		SharingModel: constants.SharingModelPrivate,
		Fields: []models.FieldMetadata{{
			ID: "field-parent-id", APIName: constants.FieldID, Label: "ID",
			Type: constants.FieldTypeString, PhysicalName: "parent_id", IsSystem: true,
		}},
	}
	child := &models.ObjectMetadata{
		ID: "object-child", APIName: "Child", Label: "Child", PluralLabel: "Children",
		SharingModel: constants.SharingModelControlledByParent,
		Fields: []models.FieldMetadata{
			{ID: "field-child-id", APIName: constants.FieldID, Label: "ID", Type: constants.FieldTypeString, PhysicalName: "child_id", IsSystem: true},
			{ID: "field-child-parent", APIName: "ParentId", Label: "Parent", Type: constants.FieldTypeMasterDetail, PhysicalName: "parent_id", Required: true, IsMasterDetail: true, ReferenceTo: []string{"Parent"}},
		},
	}
	input := catalogsnapshot.CompileInput{
		OrgID:   "org-runtime-effective-permission-test",
		Lineage: catalogsnapshot.Lineage{CatalogRevision: 1, SchemaGeneration: 1, EngineGeneration: 1},
		Objects: []catalogsnapshot.ObjectInput{
			{CatalogRevision: 1, Metadata: parent},
			{CatalogRevision: 1, Metadata: child},
		},
		Relationships: []catalogsnapshot.RelationshipInput{{CatalogRevision: 1, Metadata: &models.Relationship{
			ID: "relationship-child-parent", ChildObjectAPIName: "Child", ParentObjectAPIName: "Parent",
			FieldAPIName: "ParentId", RelationshipType: "masterdetail", IsSharingParent: true,
		}}},
		MutationDefinitions: []catalogsnapshot.MutationDefinitionInput{{CatalogRevision: 1, RecordType: &models.RecordType{
			ID: "record-type-parent", ObjectAPIName: "Parent", DeveloperName: "Parent", Name: "Parent", IsActive: true,
		}}},
		Projections: []catalogsnapshot.RuntimeProjectionInput{{
			CatalogRevision: 1, AppInstallationID: installation, CapabilityID: capability,
			Profile: catalogsnapshot.ProjectionEffectivePermissionsV1, ObjectAPINames: []string{"Child", "Parent"},
		}},
	}
	snapshotArtifact, err := catalogsnapshot.CompileCatalogSnapshot(input)
	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, CapabilityID: capability,
	})
	if err != nil {
		t.Fatal(err)
	}
	view, err := catalogsnapshot.OpenRuntimeMetadataView(viewArtifact)
	if err != nil {
		t.Fatal(err)
	}
	return view
}

func runtimeQueryMetadataServiceView(t *testing.T) *catalogsnapshot.RuntimeMetadataView {
	t.Helper()
	const (
		installation = "installation-runtime-query-metadata-test"
		capability   = "runtime.records.query.v1"
	)
	workspace := &models.ObjectMetadata{
		ID: "object-workspace", APIName: "Workspace", Label: "Workspace", PluralLabel: "Workspaces",
		SharingModel: constants.SharingModelPublicReadWrite,
		Fields:       []models.FieldMetadata{{ID: "field-workspace-id", APIName: "Id", Label: "ID", Type: constants.FieldTypeString, PhysicalName: "id", IsSystem: true}},
	}
	workItem := &models.ObjectMetadata{
		ID: "object-work-item", APIName: "WorkItem", Label: "Work Item", PluralLabel: "Work Items",
		SharingModel: constants.SharingModelPublicReadWrite,
		Fields: []models.FieldMetadata{
			{ID: "field-work-item-id", APIName: "Id", Label: "ID", Type: constants.FieldTypeString, PhysicalName: "id", IsSystem: true},
			{ID: "field-work-item-workspace", APIName: "WorkspaceId", Label: "Workspace", Type: constants.FieldTypeReference, PhysicalName: "workspace_id", ReferenceTo: []string{"Workspace"}},
		},
	}
	snapshotArtifact, err := catalogsnapshot.CompileCatalogSnapshot(catalogsnapshot.CompileInput{
		OrgID:   "org-runtime-query-metadata-test",
		Lineage: catalogsnapshot.Lineage{CatalogRevision: 1, SchemaGeneration: 1, EngineGeneration: 1},
		Objects: []catalogsnapshot.ObjectInput{
			{CatalogRevision: 1, Metadata: workspace},
			{CatalogRevision: 1, Metadata: workItem},
		},
		Relationships: []catalogsnapshot.RelationshipInput{{CatalogRevision: 1, Metadata: &models.Relationship{
			ID: "relationship-workspace", ChildObjectAPIName: "WorkItem", ParentObjectAPIName: "Workspace",
			FieldAPIName: "WorkspaceId", RelationshipName: "Workspace", RelationshipType: "lookup",
		}}},
		Projections: []catalogsnapshot.RuntimeProjectionInput{{
			CatalogRevision: 1, AppInstallationID: installation, CapabilityID: capability,
			Profile: catalogsnapshot.ProjectionRecordQueryV1, ObjectAPINames: []string{"WorkItem", "Workspace"},
		}},
	})
	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, CapabilityID: capability,
	})
	if err != nil {
		t.Fatal(err)
	}
	view, err := catalogsnapshot.OpenRuntimeMetadataView(viewArtifact)
	if err != nil {
		t.Fatal(err)
	}
	return view
}

func runtimeMutationMetadataServiceView(t testing.TB) *catalogsnapshot.RuntimeMetadataView {
	t.Helper()
	const (
		installation = "installation-runtime-mutation-metadata-test"
		capability   = "runtime.records.mutate.v1"
	)
	keyPrefix := "0WD"
	recordTypeRelationship := constants.ObjectRecordType
	snapshotArtifact, err := catalogsnapshot.CompileCatalogSnapshot(catalogsnapshot.CompileInput{
		OrgID:   "org-runtime-mutation-metadata-test",
		Lineage: catalogsnapshot.Lineage{CatalogRevision: 1, SchemaGeneration: 1, EngineGeneration: 1},
		Objects: []catalogsnapshot.ObjectInput{{CatalogRevision: 1, Metadata: &models.ObjectMetadata{
			ID: "object-widget", APIName: "Widget", Label: "Widget", PluralLabel: "Widgets",
			SharingModel: constants.SharingModelPublicReadWrite, KeyPrefix: &keyPrefix,
			Fields: []models.FieldMetadata{
				{
					ID: "field-widget-id", APIName: constants.FieldID, Label: "ID",
					Type: constants.FieldTypeString, PhysicalName: constants.FieldID, IsSystem: true,
				},
				{
					ID: "field-widget-record-type", APIName: constants.FieldRecordTypeID, Label: "Record Type",
					Type: constants.FieldTypeReference, PhysicalName: constants.FieldRecordTypeID,
					ReferenceTo: []string{constants.ObjectRecordType}, RelationshipName: &recordTypeRelationship,
				},
			},
		}}},
		MutationDefinitions: []catalogsnapshot.MutationDefinitionInput{
			{CatalogRevision: 1, ValidationRule: &models.ValidationRule{
				ID: "validation-widget", ObjectAPIName: "Widget", Name: "ValidateWidget",
				Active: true, Condition: "false", ErrorMessage: "invalid",
			}},
			{CatalogRevision: 1, RecordType: &models.RecordType{
				ID: "record-type-widget", ObjectAPIName: "Widget", Name: "WidgetType",
				DeveloperName: "WidgetType", IsActive: true,
			}},
		},
		Projections: []catalogsnapshot.RuntimeProjectionInput{{
			CatalogRevision: 1, AppInstallationID: installation, CapabilityID: capability,
			Profile: catalogsnapshot.ProjectionRecordMutationV1, ObjectAPINames: []string{"Widget"},
		}},
	})
	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, CapabilityID: capability,
	})
	if err != nil {
		t.Fatal(err)
	}
	view, err := catalogsnapshot.OpenRuntimeMetadataView(viewArtifact)
	if err != nil {
		t.Fatal(err)
	}
	return view
}

func runtimeApprovalMutationMetadataServiceView(t *testing.T) *catalogsnapshot.RuntimeMetadataView {
	t.Helper()
	const (
		installation = "installation-runtime-approval-metadata-test"
		definitionID = "approval.widget.primary"
	)
	order := 1
	definition := &approvalir.Definition{
		Label: "Widget approval", Active: true, ProcessOrder: &order,
		Policy: approvalir.ApprovalPolicy{
			RecordEditability: approvalir.RecordEditabilityAdminOnly,
			AllowedSubmitters: []approvalir.AllowedSubmitter{{Kind: approvalir.SubmitterKindAllInternalUsers}},
		},
		Steps: []approvalir.Step{{
			Name: "Review", Label: "Review",
			Approvers:      []approvalir.Approver{{Kind: approvalir.ApproverKindUser, Reference: "user-reviewer"}},
			RejectBehavior: approvalir.RejectBehaviorFinalRejection,
		}},
	}
	envelope, err := approvalir.EncodeDefinitionEnvelope([]byte("runtime metadata approval source"), definition, nil)
	if err != nil {
		t.Fatal(err)
	}
	keyPrefix := "0WD"
	snapshotArtifact, err := catalogsnapshot.CompileCatalogSnapshot(catalogsnapshot.CompileInput{
		OrgID:   "org-runtime-approval-metadata-test",
		Lineage: catalogsnapshot.Lineage{CatalogRevision: 1, SchemaGeneration: 1, EngineGeneration: 1},
		Objects: []catalogsnapshot.ObjectInput{{CatalogRevision: 1, Metadata: &models.ObjectMetadata{
			ID: "object-widget", APIName: "Widget", Label: "Widget", PluralLabel: "Widgets",
			SharingModel: constants.SharingModelPublicReadWrite, KeyPrefix: &keyPrefix,
			Fields: []models.FieldMetadata{{
				ID: "field-widget-id", APIName: constants.FieldID, Label: "ID",
				Type: constants.FieldTypeString, PhysicalName: constants.FieldID, IsSystem: true,
			}},
		}}},
		MutationDefinitions: []catalogsnapshot.MutationDefinitionInput{{
			CatalogRevision: 1,
			ValidationRule: &models.ValidationRule{
				ID: "validation-widget", ObjectAPIName: "Widget", Name: "ValidateWidget",
				Active: true, Condition: "false", ErrorMessage: "invalid",
			},
		}},
		ApprovalDefinitions: []catalogsnapshot.ApprovalDefinitionInput{{
			CatalogRevision: 1, DefinitionID: definitionID,
			ObjectAPIName: "Widget", DeveloperName: "Primary", Envelope: envelope,
		}},
		Projections: []catalogsnapshot.RuntimeProjectionInput{{
			CatalogRevision: 1, AppInstallationID: installation,
			CapabilityID:   approvalv1.ExecuteCapabilityName,
			Profile:        catalogsnapshot.ProjectionApprovalExecutionV1,
			ObjectAPINames: []string{"Widget"}, DefinitionComponentIDs: []string{definitionID},
		}},
	})
	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,
		CapabilityID:      approvalv1.ExecuteCapabilityName,
	})
	if err != nil {
		t.Fatal(err)
	}
	view, err := catalogsnapshot.OpenRuntimeMetadataView(viewArtifact)
	if err != nil {
		t.Fatal(err)
	}
	return view
}

func TestRuntimeGetAllObjectsRequiresAndPreservesRequestView(t *testing.T) {
	service, err := NewRuntimeMetadataService(RuntimeMetadataViewFromContext)
	if err != nil {
		t.Fatal(err)
	}
	view := runtimeMetadataServiceView(t)
	ctx := WithRuntimeMetadataView(t.Context(), view)
	objects, err := service.GetAllObjects(ctx, &models.UserSession{ID: "reader"})
	if err != nil || len(objects) != 1 || objects[0].APIName != "Widget" {
		t.Fatalf("objects=%v error=%v", objects, err)
	}
	objects[0].APIName = "mutated"
	objects[0].Fields[0].Label = "mutated"
	again, err := service.GetAllObjects(ctx, &models.UserSession{ID: "reader"})
	if err != nil || again[0].APIName != "Widget" || again[0].Fields[0].Label == "mutated" {
		t.Fatal("enumeration mutated immutable view")
	}
	if got, err := service.GetAllObjects(context.Background(), nil); err == nil || len(got) != 0 {
		t.Fatal("missing request view did not fail closed")
	}
}
