package consumerv1

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"sort"
	"strings"
	"testing"
	"time"

	"github.com/pingcap-inc/nexuscrm-contract/pkg/appauthority"
	common "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/commonv1"
)

func TestConsumerViewsRejectOversizedProjectionBeforeDigestWork(t *testing.T) {
	appView := validAppMetadataView(t, 5)
	appView.Components[0].CanonicalBehavior = []byte(strings.Repeat("x", MaxSemanticResponseBytes))
	requireResourceExhausted(t, ValidateAppMetadataView(appView), MaxSemanticResponseBytes)

	v2View := validAppMetadataViewV2(t, 5)
	v2View.EffectiveComponents[0].CanonicalBehavior =
		[]byte(strings.Repeat("x", MaxSemanticResponseBytes))
	requireResourceExhausted(t, ValidateAppMetadataViewV2(v2View), MaxSemanticResponseBytes)

	v3View := validAppMetadataViewV3(t, 5)
	v3View.EffectiveComponents[0].CanonicalBehavior =
		[]byte(strings.Repeat("x", MaxAppMetadataV3SemanticResponseBytes))
	requireResourceExhausted(
		t,
		ValidateAppMetadataViewV3(v3View),
		MaxAppMetadataV3SemanticResponseBytes,
	)

	integrationView := validIntegrationBindingView(5)
	integrationView.Bindings = make([]IntegrationBinding, 17)
	for bindingIndex := range integrationView.Bindings {
		binding := IntegrationBinding{
			Kind: BindingConnectorInboundRoute, OwnerPack: "connector-neutral",
			PackInstallationID: "pack-install-1",
			PackPayloadDigest:  "nexus-pack-sha256-v1:" + strings.Repeat("a", 64),
			BusinessKey:        fmt.Sprintf("event-%03d", bindingIndex),
			DefinitionVersion:  1,
			CredentialRefs:     make([]string, MaxCredentialRefCount),
		}
		for credentialIndex := range binding.CredentialRefs {
			prefix := fmt.Sprintf("credential-%03d-", credentialIndex)
			binding.CredentialRefs[credentialIndex] = prefix +
				strings.Repeat("x", MaxIdentifierBytes-len(prefix))
		}
		integrationView.Bindings[bindingIndex] = binding
	}
	requireResourceExhausted(
		t,
		ValidateIntegrationBindingView(integrationView),
		MaxSemanticResponseBytes,
	)
}

func TestCatalogSemanticResponseBudgetCoversProductionShapedClosure(t *testing.T) {
	// Measured from the isolated D3 production clone at Catalog revision 3.
	// Both portions are required in one immutable V3 response; testing only the
	// effective portion previously hid JSON's base64 expansion of the App bytes.
	const (
		productionAppBehaviorBytes       = 231549
		productionEffectiveBehaviorBytes = 1384369
	)
	if MaxSemanticResponseBytes != 1024*1024 {
		t.Fatalf("published Catalog semantic response budget = %d, want 1 MiB", MaxSemanticResponseBytes)
	}
	if MaxAppMetadataV3SemanticResponseBytes != 3*1024*1024 {
		t.Fatalf(
			"App metadata V3 semantic response budget = %d, want 3 MiB",
			MaxAppMetadataV3SemanticResponseBytes,
		)
	}
	view := validAppMetadataViewV3(t, 5)
	view.AppComponents[0].CanonicalBehavior =
		[]byte(strings.Repeat("a", productionAppBehaviorBytes))
	var err error
	view.AppComponents[0].ContentDigest, err = appauthority.ComponentDigest(
		view.AppComponents[0].ComponentKind,
		view.AppComponents[0].ComponentFormatVersion,
		view.AppComponents[0].CanonicalBehavior,
	)
	if err != nil {
		t.Fatal(err)
	}
	view.EffectiveComponents[0].CanonicalBehavior =
		[]byte(strings.Repeat("e", productionEffectiveBehaviorBytes))
	view.EffectiveComponents[0].ContentDigest =
		ComputeEffectiveMetadataComponentDigest(
			view.EffectiveComponents[0].CanonicalBehavior,
		)
	if ValidateEffectiveMetadataComponent(view.EffectiveComponents[0]) == nil {
		t.Fatal("published V2 component validator accepted a component above 1 MiB")
	}
	if err := ValidateEffectiveMetadataComponentForCapability(
		view.EffectiveComponents[0],
		AppMetadataV3CapabilityName,
	); err != nil {
		t.Fatalf("V3 component validator rejected the production-shaped component: %v", err)
	}
	view.Lineage.ViewDigest = ComputeAppMetadataViewV3Digest(view)
	if err := ValidateAppMetadataViewV3(view); err != nil {
		t.Fatalf("production-shaped Catalog closure was rejected: %v", err)
	}
	v2View := AppMetadataViewV2{
		OrgID: view.OrgID, AppInstallationID: view.AppInstallationID,
		AppID: view.AppID, AppReleaseDigest: view.AppReleaseDigest,
		Lineage: view.Lineage, AppComponents: view.AppComponents,
		EffectiveComponents: view.EffectiveComponents, Receipts: view.Receipts,
	}
	v2View.Receipts.CapabilityVersion = AppMetadataV2CapabilityName
	v2View.Lineage.ViewDigest = ComputeAppMetadataViewV2Digest(v2View)
	requireResourceExhausted(
		t,
		ValidateAppMetadataViewV2(v2View),
		MaxSemanticResponseBytes,
	)
	encoded, err := json.Marshal(view)
	if err != nil {
		t.Fatal(err)
	}
	if len(encoded) <= 2*1024*1024 || len(encoded) > MaxAppMetadataV3SemanticResponseBytes {
		t.Fatalf(
			"production-shaped Catalog semantic response bytes = %d, want > 2 MiB and <= %d",
			len(encoded), MaxAppMetadataV3SemanticResponseBytes,
		)
	}
}

func TestComponentValidationUsesCapabilityResponseBudget(t *testing.T) {
	view := validAppMetadataViewV3(t, 5)
	behavior := []byte(strings.Repeat("x", MaxSemanticResponseBytes+1))

	appComponent := view.AppComponents[0]
	appComponent.CanonicalBehavior = behavior
	var err error
	appComponent.ContentDigest, err = appauthority.ComponentDigest(
		appComponent.ComponentKind,
		appComponent.ComponentFormatVersion,
		appComponent.CanonicalBehavior,
	)
	if err != nil {
		t.Fatal(err)
	}
	if ValidateAppMetadataComponent(appComponent) == nil {
		t.Fatal("published App component validator accepted a component above 1 MiB")
	}
	if ValidateAppMetadataComponentForCapability(
		appComponent,
		AppMetadataV2CapabilityName,
	) == nil {
		t.Fatal("V2 App component validator accepted a component above 1 MiB")
	}
	if err := ValidateAppMetadataComponentForCapability(
		appComponent,
		AppMetadataV3CapabilityName,
	); err != nil {
		t.Fatalf("V3 App component validator rejected a component below 3 MiB: %v", err)
	}

	effectiveComponent := view.EffectiveComponents[0]
	effectiveComponent.CanonicalBehavior = behavior
	effectiveComponent.ContentDigest = ComputeEffectiveMetadataComponentDigest(behavior)
	if ValidateEffectiveMetadataComponent(effectiveComponent) == nil {
		t.Fatal("published effective component validator accepted a component above 1 MiB")
	}
	if ValidateEffectiveMetadataComponentForCapability(
		effectiveComponent,
		AppMetadataV2CapabilityName,
	) == nil {
		t.Fatal("V2 effective component validator accepted a component above 1 MiB")
	}
	if err := ValidateEffectiveMetadataComponentForCapability(
		effectiveComponent,
		AppMetadataV3CapabilityName,
	); err != nil {
		t.Fatalf("V3 effective component validator rejected a component below 3 MiB: %v", err)
	}
	if ValidateEffectiveMetadataComponentForCapability(
		effectiveComponent,
		AppMetadataCapabilityName,
	) == nil {
		t.Fatal("V1 accepted an effective component it does not carry")
	}
	if ValidateAppMetadataComponentForCapability(appComponent, "unknown") == nil {
		t.Fatal("unknown capability selected an App component response budget")
	}
}

func TestRuntimeCommandSemanticBudgetChargesCompleteDigestFraming(t *testing.T) {
	command := RuntimeCommandBinding{
		CommandKind:          "runtime.flow.execute",
		PayloadFormatVersion: 1,
		DefinitionRef:        "flow.neutral",
		DefinitionVersion:    "flow-version-7",
	}
	budget := newSemanticBudget(MaxSemanticResponseBytes)
	before := budget.remaining
	budget.addRuntimeCommandBinding(&command)
	wantCharge := 4 +
		8 + len(command.CommandKind) +
		4 +
		8 + len(command.DefinitionRef) +
		8 + len(command.DefinitionVersion)
	if got := before - budget.remaining; got != wantCharge {
		t.Fatalf(
			"Runtime command budget charge = %d, want complete digest framing %d",
			got,
			wantCharge,
		)
	}
}

func TestAppMetadataV2BindsAppAndEffectiveComponentsToOneRevision(t *testing.T) {
	view := validAppMetadataViewV2(t, 5)
	if err := ValidateAppMetadataViewV2(view); err != nil {
		t.Fatalf("ValidateAppMetadataViewV2() error = %v", err)
	}

	changed := view
	changed.EffectiveComponents = append(
		[]EffectiveMetadataComponent(nil), view.EffectiveComponents...,
	)
	changed.EffectiveComponents[0].CanonicalBehavior =
		[]byte(`{"objects":["changed"]}`)
	changed.EffectiveComponents[0].ContentDigest =
		ComputeEffectiveMetadataComponentDigest(
			changed.EffectiveComponents[0].CanonicalBehavior,
		)
	if ValidateAppMetadataViewV2(changed) == nil {
		t.Fatal("effective component changed without advancing the view digest")
	}

	changed = validAppMetadataViewV2(t, 5)
	changed.Receipts.CatalogRevision++
	if ValidateAppMetadataViewV2(changed) == nil {
		t.Fatal("mixed-revision v2 view was accepted")
	}

	changed = validAppMetadataViewV2(t, 5)
	changed.EffectiveComponents = append(
		changed.EffectiveComponents, changed.EffectiveComponents[0],
	)
	changed.Lineage.ViewDigest = ComputeAppMetadataViewV2Digest(changed)
	if ValidateAppMetadataViewV2(changed) == nil {
		t.Fatal("duplicate effective component identity was accepted")
	}
}

func TestIntegrationViewBindsExactGenerationReferences(t *testing.T) {
	view := validIntegrationBindingView(5)
	if err := ValidateIntegrationBindingView(view); err != nil {
		t.Fatalf("ValidateIntegrationBindingView() error = %v", err)
	}
	mixed := view
	mixed.Bindings = append([]IntegrationBinding(nil), view.Bindings...)
	mixed.Bindings[0].DefinitionVersion++
	if ValidateIntegrationBindingView(mixed) == nil {
		t.Fatal("binding changed without advancing the view digest was accepted")
	}
	mixed = validIntegrationBindingView(5)
	mixed.Bindings[0].PackPayloadDigest = "sha256:" + strings.Repeat("a", 64)
	mixed.Lineage.ViewDigest = ComputeIntegrationBindingViewDigest(mixed)
	if ValidateIntegrationBindingView(mixed) == nil {
		t.Fatal("binding with a non-authoritative pack digest was accepted")
	}

	mixed = integrationBindingViewWithRuntimeCommand(5)
	mixed.Bindings[0].RuntimeCommand.DefinitionVersion = "flow-version-2"
	if ValidateIntegrationBindingView(mixed) == nil {
		t.Fatal("runtime command identity changed without advancing the view digest was accepted")
	}
}

func TestIntegrationRuntimeCommandBindingIsClosedAndExecutionFactScoped(t *testing.T) {
	view := integrationBindingViewWithRuntimeCommand(5)
	for name, mutate := range map[string]func(*RuntimeCommandBinding){
		"command kind":           func(binding *RuntimeCommandBinding) { binding.CommandKind = "" },
		"payload format version": func(binding *RuntimeCommandBinding) { binding.PayloadFormatVersion = 0 },
		"definition ref":         func(binding *RuntimeCommandBinding) { binding.DefinitionRef = "" },
		"definition version":     func(binding *RuntimeCommandBinding) { binding.DefinitionVersion = "" },
	} {
		t.Run(name, func(t *testing.T) {
			changed := view
			changed.Bindings = append([]IntegrationBinding(nil), view.Bindings...)
			command := *view.Bindings[0].RuntimeCommand
			changed.Bindings[0].RuntimeCommand = &command
			mutate(changed.Bindings[0].RuntimeCommand)
			changed.Lineage.ViewDigest = ComputeIntegrationBindingViewDigest(changed)
			if ValidateIntegrationBindingView(changed) == nil {
				t.Fatalf("partial runtime command binding with empty %s was accepted", name)
			}
		})
	}

	pushContract := view
	pushContract.Bindings = append([]IntegrationBinding(nil), view.Bindings...)
	pushContract.Bindings[0].Kind = BindingConnectorPushContract
	pushContract.Lineage.ViewDigest = ComputeIntegrationBindingViewDigest(pushContract)
	if err := ValidateIntegrationBindingView(pushContract); err != nil {
		t.Fatalf("runtime command binding on a push contract was rejected: %v", err)
	}

	for _, kind := range []IntegrationBindingKind{
		BindingConnectorCalloutProfile,
		BindingConnectorFieldMapping,
	} {
		nonExecutionFact := view
		nonExecutionFact.Bindings = append([]IntegrationBinding(nil), view.Bindings...)
		nonExecutionFact.Bindings[0].Kind = kind
		nonExecutionFact.Lineage.ViewDigest = ComputeIntegrationBindingViewDigest(nonExecutionFact)
		if ValidateIntegrationBindingView(nonExecutionFact) == nil {
			t.Fatalf("runtime command binding on %s was accepted", kind)
		}
	}
	invalidCommandKind := view
	invalidCommandKind.Bindings = append(
		[]IntegrationBinding(nil),
		view.Bindings...,
	)
	command := *view.Bindings[0].RuntimeCommand
	command.CommandKind = "runtime flow execute"
	invalidCommandKind.Bindings[0].RuntimeCommand = &command
	invalidCommandKind.Lineage.ViewDigest =
		ComputeIntegrationBindingViewDigest(invalidCommandKind)
	if ValidateIntegrationBindingView(invalidCommandKind) == nil {
		t.Fatal("runtime command kind outside the acceptance grammar was accepted")
	}

	nMinusOne := view
	nMinusOne.Bindings = append([]IntegrationBinding(nil), view.Bindings...)
	nMinusOne.Bindings[0].RuntimeCommand = nil
	nMinusOne.Lineage.ViewDigest = ComputeIntegrationBindingViewDigest(nMinusOne)
	if err := ValidateIntegrationBindingView(nMinusOne); err != nil {
		t.Fatalf("N-1 route without an additive runtime command binding was rejected: %v", err)
	}
}

func TestIntegrationNMinusOneJSONBoundaryOmitsAdditiveRuntimeCommand(t *testing.T) {
	type nMinusOneBinding struct {
		Kind               IntegrationBindingKind
		OwnerPack          string
		PackInstallationID string
		PackPayloadDigest  string
		BusinessKey        string
		DefinitionVersion  uint64
		CredentialRefs     []string
	}
	binding := validIntegrationBindingView(5).Bindings[0]
	got, err := json.Marshal(binding)
	if err != nil {
		t.Fatalf("marshal additive binding: %v", err)
	}
	want, err := json.Marshal(nMinusOneBinding{
		Kind:               binding.Kind,
		OwnerPack:          binding.OwnerPack,
		PackInstallationID: binding.PackInstallationID,
		PackPayloadDigest:  binding.PackPayloadDigest,
		BusinessKey:        binding.BusinessKey,
		DefinitionVersion:  binding.DefinitionVersion,
		CredentialRefs:     binding.CredentialRefs,
	})
	if err != nil {
		t.Fatalf("marshal N-1 binding: %v", err)
	}
	if string(got) != string(want) {
		t.Fatalf("nil additive field changed N-1 JSON size boundary:\n got %s\nwant %s", got, want)
	}
}

func TestConsumerViewsBindLineageAndAuthority(t *testing.T) {
	behavior := []byte("opaque-behavior")
	component := AppMetadataComponent{
		ComponentKind: "metadata.app.neutral.v1", ComponentFormatVersion: 1,
		NamespaceID: "io.nexuscrm.neutral", BusinessKey: "component", DefinitionVersion: "1",
		CanonicalBehavior: behavior,
	}
	component.ComponentID = appauthority.ComponentID(component.NamespaceID, component.ComponentKind, component.BusinessKey)
	var err error
	component.ContentDigest, err = appauthority.ComponentDigest(component.ComponentKind, component.ComponentFormatVersion, behavior)
	if err != nil {
		t.Fatal(err)
	}
	lineage := ViewLineage{
		CatalogRevision: 7, SchemaGeneration: 7, EngineGeneration: 7,
		SourceSnapshotDigest: "sha256:" + strings.Repeat("b", 64),
		ViewDigest:           "sha256:" + strings.Repeat("c", 64),
	}
	view := AppMetadataView{
		OrgID: "org-1", AppInstallationID: "01900000-0000-7000-8000-000000000001",
		AppID: "io.nexuscrm.neutral", AppReleaseDigest: "sha256:" + strings.Repeat("d", 64),
		Lineage: lineage, Components: []AppMetadataComponent{component},
		Receipts: Receipts{ProtocolVersion: "1.0", CapabilityVersion: AppMetadataCapabilityName,
			CatalogRevision: 7, SchemaGeneration: 7, EngineGeneration: 7},
	}
	view.Lineage.ViewDigest = ComputeAppMetadataViewDigest(view)
	if err := ValidateAppMetadataView(view); err != nil {
		t.Fatalf("ValidateAppMetadataView() error = %v", err)
	}
	wrongScope := view
	wrongScope.OrgID = "org-2"
	if ValidateAppMetadataView(wrongScope) == nil {
		t.Fatal("view digest not bound to caller scope")
	}
	view.Receipts.CatalogRevision++
	if ValidateAppMetadataView(view) == nil {
		t.Fatal("mixed-revision view was accepted")
	}
}

func TestConsumerRequestsRequireLiveDeadline(t *testing.T) {
	ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second))
	defer cancel()
	if err := ValidateGetRequest(ctx, GetRequest{}); err != nil {
		t.Fatalf("ValidateGetRequest() error = %v", err)
	}
	if err := ValidateWatchRequest(ctx, WatchRequest{}); err != nil {
		t.Fatalf("ValidateWatchRequest() error = %v", err)
	}
	if ValidateGetRequest(context.Background(), GetRequest{}) == nil {
		t.Fatal("request without a deadline was accepted")
	}
}

func TestIntegrationViewRejectsDuplicateAndUnsortedAuthority(t *testing.T) {
	makeBinding := func(key string) IntegrationBinding {
		binding := IntegrationBinding{
			Kind: BindingConnectorCalloutProfile, OwnerPack: "connector-neutral",
			PackInstallationID: "pack-install-1",
			PackPayloadDigest:  "nexus-pack-sha256-v1:" + strings.Repeat("a", 64),
			BusinessKey:        key, DefinitionVersion: 1,
			CredentialRefs: []string{"credential-b", "credential-a"},
		}
		return binding
	}
	binding := makeBinding("profile")
	unsorted := validIntegrationBindingView(5)
	unsorted.Bindings = []IntegrationBinding{binding}
	unsorted.Lineage.ViewDigest = ComputeIntegrationBindingViewDigest(unsorted)
	if ValidateIntegrationBindingView(unsorted) == nil {
		t.Fatal("unsorted credential authority was accepted")
	}
	sort.Strings(binding.CredentialRefs)
	lineage := ViewLineage{CatalogRevision: 5, SchemaGeneration: 5, EngineGeneration: 5,
		SourceSnapshotDigest: "sha256:" + strings.Repeat("b", 64), ViewDigest: "sha256:" + strings.Repeat("c", 64)}
	view := IntegrationBindingView{
		OrgID: "org-1", AppInstallationID: "01900000-0000-7000-8000-000000000001",
		AuthorizedWorkloadID: "integration", Lineage: lineage,
		Bindings: []IntegrationBinding{binding, binding},
		Receipts: common.Receipts{ProtocolVersion: "1.0", CapabilityVersion: IntegrationBindingCapabilityName,
			CatalogRevision: 5, SchemaGeneration: 5, EngineGeneration: 5},
	}
	view.Lineage.ViewDigest = ComputeIntegrationBindingViewDigest(view)
	if ValidateIntegrationBindingView(view) == nil {
		t.Fatal("duplicate binding authority was accepted")
	}
}

func TestWatchStateIsMonotonicAndScopeBound(t *testing.T) {
	view := validAppMetadataView(t, 5)
	after := uint64(4)
	state := NewAppMetadataWatchState(WatchRequest{AfterCatalogRevision: &after})
	if err := state.Observe(view); err != nil {
		t.Fatalf("Observe(first) error = %v", err)
	}
	if state.Observe(view) == nil {
		t.Fatal("duplicate Catalog revision was accepted")
	}
	next := validAppMetadataView(t, 6)
	next.AppInstallationID = "01900000-0000-7000-8000-000000000002"
	if state.Observe(next) == nil {
		t.Fatal("cross-installation watch response was accepted")
	}
}

func TestAppMetadataV2WatchStateIsMonotonicAndScopeBound(t *testing.T) {
	view := validAppMetadataViewV2(t, 5)
	after := uint64(4)
	state := NewAppMetadataV2WatchState(
		WatchRequest{AfterCatalogRevision: &after},
	)
	if err := state.Observe(view); err != nil {
		t.Fatalf("Observe(first) error = %v", err)
	}
	if state.Observe(view) == nil {
		t.Fatal("duplicate Catalog revision was accepted")
	}
	next := validAppMetadataViewV2(t, 6)
	next.AppID = "io.nexuscrm.other"
	next.Lineage.ViewDigest = ComputeAppMetadataViewV2Digest(next)
	if state.Observe(next) == nil {
		t.Fatal("cross-App watch response was accepted")
	}
}

func TestAppMetadataV3WatchStateIsMonotonicAndScopeBound(t *testing.T) {
	view := validAppMetadataViewV3(t, 5)
	after := uint64(4)
	state := NewAppMetadataV3WatchState(
		WatchRequest{AfterCatalogRevision: &after},
	)
	if err := state.Observe(view); err != nil {
		t.Fatalf("Observe(first) error = %v", err)
	}
	if state.Observe(view) == nil {
		t.Fatal("duplicate Catalog revision was accepted")
	}
	next := validAppMetadataViewV3(t, 6)
	next.AppID = "io.nexuscrm.other"
	next.Lineage.ViewDigest = ComputeAppMetadataViewV3Digest(next)
	if state.Observe(next) == nil {
		t.Fatal("cross-App watch response was accepted")
	}
}

func TestDigestVectors(t *testing.T) {
	appView := validAppMetadataView(t, 5)
	appV2View := validAppMetadataViewV2(t, 5)
	appV3View := validAppMetadataViewV3(t, 5)
	integrationView := validIntegrationBindingView(5)
	vectors := map[string][2]string{
		"App view digest": {
			appView.Lineage.ViewDigest,
			"sha256:18ea9d9d491423a281e94e8246e3f5656e0ce9ee46bb19672104e7a32045deed",
		},
		"App v2 view digest": {
			appV2View.Lineage.ViewDigest,
			"sha256:58d38714d80a6d2124abff3e03fa0f69ac72dea66fcdb761cc5769137290064f",
		},
		"App v3 view digest": {
			appV3View.Lineage.ViewDigest,
			"sha256:d3d9f65d38e5d7c162beead8316f8b767e94a9eb3c015ad44bd1e54e111096ba",
		},
		"Integration view digest": {
			integrationView.Lineage.ViewDigest,
			"sha256:4baacf0cf7295171dbd66b697c483b1d6be82101d944c334339b633ab2e725a4",
		},
	}
	for name, vector := range vectors {
		if vector[0] != vector[1] {
			t.Fatalf("%s = %s, want immutable vector %s", name, vector[0], vector[1])
		}
	}
}

func validAppMetadataViewV2(
	t *testing.T,
	revision uint64,
) AppMetadataViewV2 {
	t.Helper()
	v1 := validAppMetadataView(t, revision)
	effectiveBehavior := []byte(`{"objects":["Account","Contact"]}`)
	view := AppMetadataViewV2{
		OrgID:             v1.OrgID,
		AppInstallationID: v1.AppInstallationID,
		AppID:             v1.AppID,
		AppReleaseDigest:  v1.AppReleaseDigest,
		Lineage: ViewLineage{
			CatalogRevision:      revision,
			SchemaGeneration:     revision,
			EngineGeneration:     revision,
			SourceSnapshotDigest: v1.Lineage.SourceSnapshotDigest,
		},
		AppComponents: append(
			[]AppMetadataComponent(nil), v1.Components...,
		),
		EffectiveComponents: []EffectiveMetadataComponent{{
			ComponentKind:          "metadata.effective.objects.v1",
			ComponentFormatVersion: 1,
			BusinessKey:            "objects",
			ContentDigest: ComputeEffectiveMetadataComponentDigest(
				effectiveBehavior,
			),
			CanonicalBehavior: effectiveBehavior,
		}},
		Receipts: Receipts{
			ProtocolVersion:   "1.0",
			CapabilityVersion: AppMetadataV2CapabilityName,
			CatalogRevision:   revision,
			SchemaGeneration:  revision,
			EngineGeneration:  revision,
		},
	}
	view.Lineage.ViewDigest = ComputeAppMetadataViewV2Digest(view)
	return view
}

func validAppMetadataViewV3(
	t *testing.T,
	revision uint64,
) AppMetadataViewV3 {
	t.Helper()
	v2 := validAppMetadataViewV2(t, revision)
	view := AppMetadataViewV3{
		OrgID: v2.OrgID, AppInstallationID: v2.AppInstallationID,
		AppID: v2.AppID, AppReleaseDigest: v2.AppReleaseDigest,
		Lineage: v2.Lineage, AppComponents: v2.AppComponents,
		EffectiveComponents: v2.EffectiveComponents, Receipts: v2.Receipts,
	}
	view.Receipts.CapabilityVersion = AppMetadataV3CapabilityName
	view.Lineage.ViewDigest = ComputeAppMetadataViewV3Digest(view)
	return view
}

func validIntegrationBindingView(revision uint64) IntegrationBindingView {
	view := IntegrationBindingView{
		OrgID: "org-1", AppInstallationID: "01900000-0000-7000-8000-000000000001",
		AuthorizedWorkloadID: "integration",
		Lineage: ViewLineage{
			CatalogRevision: revision, SchemaGeneration: revision, EngineGeneration: revision,
			SourceSnapshotDigest: "sha256:" + strings.Repeat("b", 64),
		},
		Bindings: []IntegrationBinding{{
			Kind: BindingConnectorInboundRoute, OwnerPack: "connector-neutral",
			PackInstallationID: "pack-install-1",
			PackPayloadDigest:  "nexus-pack-sha256-v1:" + strings.Repeat("a", 64),
			BusinessKey:        "event.created", DefinitionVersion: 3,
			CredentialRefs: []string{"credential-a"},
		}},
		Receipts: Receipts{
			ProtocolVersion: "1.0", CapabilityVersion: IntegrationBindingCapabilityName,
			CatalogRevision: revision, SchemaGeneration: revision, EngineGeneration: revision,
		},
	}
	view.Lineage.ViewDigest = ComputeIntegrationBindingViewDigest(view)
	return view
}

func integrationBindingViewWithRuntimeCommand(revision uint64) IntegrationBindingView {
	view := validIntegrationBindingView(revision)
	view.Bindings[0].RuntimeCommand = &RuntimeCommandBinding{
		CommandKind: "runtime.flow.execute", PayloadFormatVersion: 1,
		DefinitionRef: "flow-1", DefinitionVersion: "flow-version-1",
	}
	view.Lineage.ViewDigest = ComputeIntegrationBindingViewDigest(view)
	return view
}

func validAppMetadataView(t *testing.T, revision uint64) AppMetadataView {
	t.Helper()
	behavior := []byte("opaque-behavior")
	component := AppMetadataComponent{
		ComponentKind: "metadata.app.neutral.v1", ComponentFormatVersion: 1,
		NamespaceID: "io.nexuscrm.neutral", BusinessKey: "component",
		DefinitionVersion: "1", CanonicalBehavior: behavior,
	}
	component.ComponentID = appauthority.ComponentID(component.NamespaceID, component.ComponentKind, component.BusinessKey)
	var err error
	component.ContentDigest, err = appauthority.ComponentDigest(component.ComponentKind, component.ComponentFormatVersion, behavior)
	if err != nil {
		t.Fatal(err)
	}
	view := AppMetadataView{
		OrgID: "org-1", AppInstallationID: "01900000-0000-7000-8000-000000000001",
		AppID: "io.nexuscrm.neutral", AppReleaseDigest: "sha256:" + strings.Repeat("d", 64),
		Lineage: ViewLineage{CatalogRevision: revision, SchemaGeneration: revision, EngineGeneration: revision,
			SourceSnapshotDigest: "sha256:" + strings.Repeat("b", 64),
			ViewDigest:           "sha256:" + strings.Repeat("c", 64)},
		Components: []AppMetadataComponent{component},
		Receipts: Receipts{ProtocolVersion: "1.0", CapabilityVersion: AppMetadataCapabilityName,
			CatalogRevision: revision, SchemaGeneration: revision, EngineGeneration: revision},
	}
	view.Lineage.ViewDigest = ComputeAppMetadataViewDigest(view)
	return view
}

func requireResourceExhausted(t *testing.T, err error, maximum int) {
	t.Helper()
	var failure *Failure
	if !errors.As(err, &failure) ||
		failure.Category != common.FailureResourceExhausted ||
		failure.LimitKind != common.LimitSemanticResponse ||
		failure.Maximum != uint64(maximum) {
		t.Fatalf("error = %#v, want semantic-response RESOURCE_EXHAUSTED", err)
	}
}
