package catalogsnapshot

import (
	"bytes"
	"encoding/json"
	"strings"
	"testing"
	"time"

	"github.com/nexuscrm/shared/pkg/models"
	layoutauthoringv1 "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/layoutauthoringv1"
)

func TestStoredLayoutJSONProjectsExactTypedAuthoringFacts(t *testing.T) {
	storedJSON := `{
		"id":"layout-raw","objectApiName":"Account","layoutName":"Raw","type":"Detail",
		"sections":[{"id":"main","label":"Main","columns":1,"fields":[],
			"componentConfig":{"scaled":12.50,"large":9007199254740993,"precise":0.123456789012345678901234567890}}],
		"headerActions":[{"name":"save","label":"Save","type":"Standard","config":{"threshold":1e+06},
			"extensions":{"description":"Save this record"}}],
		"headerActionsAuthored":true
	}`
	var stored models.PageLayout
	decoder := json.NewDecoder(strings.NewReader(storedJSON))
	decoder.UseNumber()
	if err := decoder.Decode(&stored); err != nil {
		t.Fatal(err)
	}
	document, err := projectStoredLayoutDocument(stored)
	if err != nil {
		t.Fatal(err)
	}
	component := document.Sections[0].ComponentConfiguration
	for name, want := range map[string]string{
		"scaled": "12.50", "large": "9007199254740993", "precise": "0.123456789012345678901234567890",
	} {
		value := layoutAuthoringNamedValue(t, component, name).Value
		if value.Decimal == nil || *value.Decimal != want {
			t.Fatalf("component value %s = %#v, want exact decimal %q", name, value, want)
		}
	}
	action := document.HeaderActions.Actions[0]
	threshold := layoutAuthoringNamedValue(t, action.Configuration, "threshold").Value
	if threshold.Decimal == nil || *threshold.Decimal != "1000000" {
		t.Fatalf("legacy exponent projection = %#v, want 1000000", threshold)
	}
	description := layoutAuthoringNamedValue(t, action.Extensions, "description").Value
	if description.String == nil || *description.String != "Save this record" {
		t.Fatalf("stored action extension = %#v", description)
	}
}

func TestLayoutAuthoringProjectionIsLosslessScopedAndExactViewBound(t *testing.T) {
	input := layoutAuthoringCompileInput()
	snapshotArtifact := mustCompile(t, input)
	snapshot := mustOpenSnapshot(t, snapshotArtifact)
	if snapshot.doc.Schema != CatalogSnapshotSchemaV21 || snapshot.doc.LayoutAuthoring == nil {
		t.Fatalf("Catalog authoring schema/document = %q/%t", snapshot.doc.Schema, snapshot.doc.LayoutAuthoring != nil)
	}

	viewArtifact, err := ProjectRuntimeMetadataView(snapshot, ProjectionKey{
		AppInstallationID: testInstallA, CapabilityID: layoutauthoringv1.CapabilityName,
	})
	if err != nil {
		t.Fatal(err)
	}
	view := mustOpenView(t, viewArtifact)
	if !view.SupportsLayoutAuthoring() || view.Profile() != ProjectionLayoutAuthoringV1 ||
		view.doc.Schema != RuntimeMetadataViewSchemaV28 || len(view.Objects()) != 0 {
		t.Fatalf("authoring view support/profile/schema/objects = %v/%q/%q/%d",
			view.SupportsLayoutAuthoring(), view.Profile(), view.doc.Schema, len(view.Objects()))
	}
	if view.OrgID() != input.OrgID || view.AppInstallationID() != testInstallA ||
		view.CapabilityID() != layoutauthoringv1.CapabilityName || view.Lineage() != input.Lineage ||
		view.SourceSnapshotDigest() != snapshotArtifact.Digest() {
		t.Fatal("authoring view lost immutable scope or lineage")
	}
	store, err := NewDirectoryStore(t.TempDir())
	if err != nil {
		t.Fatal(err)
	}
	if err := store.Put(t.Context(), viewArtifact); err != nil {
		t.Fatal(err)
	}
	storedArtifact, err := store.Get(t.Context(), ArtifactRuntimeMetadataView, viewArtifact.Digest())
	if err != nil {
		t.Fatal(err)
	}
	view = mustOpenView(t, storedArtifact)

	workspace, ok := view.LayoutAuthoringWorkspace("WorkItem")
	if !ok {
		t.Fatal("WorkItem workspace is absent")
	}
	if err := layoutauthoringv1.ValidateWorkspaceResponse(
		layoutauthoringv1.WorkspaceRequest{ObjectID: "WorkItem", ViewRef: &workspace.ViewRef}, workspace,
	); err != nil {
		t.Fatalf("workspace violates semantic contract: %v", err)
	}
	if len(workspace.Layouts) != 1 || len(workspace.Assignments) != 1 ||
		workspace.Layouts[0].LayoutID != "layout-work-item" || !workspace.Layouts[0].IsDefault ||
		workspace.Assignments[0].Selectors != (layoutauthoringv1.AssignmentSelectors{}) ||
		workspace.Assignments[0].LayoutID != workspace.Layouts[0].LayoutID {
		t.Fatalf("workspace aggregate = %#v", workspace)
	}
	if _, ok := view.LayoutAuthoringWorkspace("Unrelated"); ok {
		t.Fatal("projection leaked an unselected object workspace")
	}
	assignment, ok := view.LayoutAuthoringAssignment("ASSIGNMENT-DEFAULT")
	if !ok || assignment.AssignmentID != "assignment-default" || assignment.ObjectID != "WorkItem" ||
		assignment.LayoutID != "layout-work-item" {
		t.Fatalf("assignment identity lookup = %#v, %t", assignment, ok)
	}
	if _, ok := view.LayoutAuthoringAssignment("assignment-missing"); ok {
		t.Fatal("assignment lookup invented a missing identity")
	}

	stored, ok := view.LayoutAuthoringStoredLayout("layout-work-item")
	if !ok {
		t.Fatal("stored Layout is absent")
	}
	if err := layoutauthoringv1.ValidateStoredLayoutResponse(
		layoutauthoringv1.StoredLayoutRequest{LayoutID: stored.Document.LayoutID, ViewRef: &stored.ViewRef}, stored,
	); err != nil {
		t.Fatalf("stored Layout violates semantic contract: %v", err)
	}
	if stored.ViewRef.AuthoringViewDigest != string(viewArtifact.Digest()) ||
		stored.ViewRef.CatalogRevision != uint64(testRevision) ||
		stored.AggregateVersion == stored.ResourceVersion || stored.WorkspaceVersion != workspace.WorkspaceVersion {
		t.Fatalf("stored versions/ref = %#v", stored)
	}
	if got := stored.OrderedListFields; len(got) != 2 || got[0] != "Subject" || got[1] != "Done" {
		t.Fatalf("ordered ListFields = %#v", got)
	}
	groups := stored.Document.Sections[0].FieldBehaviors
	if len(groups) != 3 || groups[0].FieldReference != "Done" || groups[0].Behaviors == nil || len(*groups[0].Behaviors) != 0 ||
		groups[1].FieldReference != "NilFact" || groups[1].Behaviors != nil ||
		groups[2].FieldReference != "Subject" || groups[2].Behaviors == nil || (*groups[2].Behaviors)[0].Behavior != "  Required  " {
		t.Fatalf("stored field-behavior presence changed: %#v", groups)
	}
	action := stored.Document.HeaderActions.Actions[0]
	threshold := layoutAuthoringNamedValue(t, action.Configuration, "threshold")
	if threshold.Value.Decimal == nil || *threshold.Value.Decimal != "12.50" {
		t.Fatalf("exact action decimal = %#v, want 12.50", threshold.Value)
	}
	description := layoutAuthoringNamedValue(t, action.Extensions, "description")
	if description.Value.String == nil || *description.Value.String != "Save this record" {
		t.Fatalf("action extension = %#v", description.Value)
	}

	// Runtime views are immutable artifacts. Returned nested slices and pointers
	// must not let one caller mutate the view observed by another caller.
	stored.Document.Sections[0].Fields[0] = "mutated"
	workspace.Assignments[0].CreatedByID = layoutAuthoringStringPointer("mutated")
	assignment.LayoutID = "mutated"
	storedAgain, _ := view.LayoutAuthoringStoredLayout("layout-work-item")
	workspaceAgain, _ := view.LayoutAuthoringWorkspace("WorkItem")
	assignmentAgain, _ := view.LayoutAuthoringAssignment("assignment-default")
	if storedAgain.Document.Sections[0].Fields[0] != "Subject" ||
		workspaceAgain.Assignments[0].CreatedByID == nil || *workspaceAgain.Assignments[0].CreatedByID != "user-1" ||
		assignmentAgain.LayoutID != "layout-work-item" {
		t.Fatal("Layout authoring accessor exposed mutable artifact storage")
	}

	effective, err := BuildEffectiveMetadata(input)
	if err != nil {
		t.Fatal(err)
	}
	openedEffective, err := OpenEffectiveMetadata(effective.Digest(), effective.Bytes())
	if err != nil {
		t.Fatal(err)
	}
	recompiled, err := CompileEffectiveMetadata(openedEffective)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(recompiled.Bytes(), snapshotArtifact.Bytes()) {
		t.Fatal("effective-metadata path changed the authoring Catalog artifact")
	}
}

func TestLayoutAuthoringOpenRejectsTamperedDerivedVersions(t *testing.T) {
	snapshot := mustOpenSnapshot(t, mustCompile(t, layoutAuthoringCompileInput()))
	artifact, err := ProjectRuntimeMetadataView(snapshot, ProjectionKey{
		AppInstallationID: testInstallA, CapabilityID: layoutauthoringv1.CapabilityName,
	})
	if err != nil {
		t.Fatal(err)
	}

	tests := []struct {
		name   string
		mutate func(*runtimeViewDocument)
	}{
		{"resource", func(doc *runtimeViewDocument) {
			doc.LayoutAuthoring.Workspaces[0].Layouts[0].ResourceVersion = "sha256:tampered"
		}},
		{"aggregate", func(doc *runtimeViewDocument) {
			doc.LayoutAuthoring.Workspaces[0].Layouts[0].AggregateVersion = "sha256:tampered"
		}},
		{"assignment", func(doc *runtimeViewDocument) {
			doc.LayoutAuthoring.Workspaces[0].Assignments[0].ResourceVersion = "sha256:tampered"
		}},
		{"workspace", func(doc *runtimeViewDocument) { doc.LayoutAuthoring.Workspaces[0].WorkspaceVersion = "sha256:tampered" }},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			var doc runtimeViewDocument
			if err := json.Unmarshal(artifact.Bytes(), &doc); err != nil {
				t.Fatal(err)
			}
			test.mutate(&doc)
			encoded, err := marshalCanonical(doc)
			if err != nil {
				t.Fatal(err)
			}
			if _, err := OpenRuntimeMetadataView(makeArtifact(ArtifactRuntimeMetadataView, encoded)); err == nil {
				t.Fatal("tampered derived version was accepted")
			}
		})
	}
}

func TestLayoutAuthoringAuthorityCannotBeDowngradedToEarlierSchemas(t *testing.T) {
	snapshotArtifact := mustCompile(t, layoutAuthoringCompileInput())
	var snapshotDoc catalogDocument
	if err := json.Unmarshal(snapshotArtifact.Bytes(), &snapshotDoc); err != nil {
		t.Fatal(err)
	}
	snapshotDoc.Schema = CatalogSnapshotSchemaV19
	encoded, err := marshalCanonical(snapshotDoc)
	if err != nil {
		t.Fatal(err)
	}
	if _, err := OpenCatalogSnapshot(makeArtifact(ArtifactCatalogSnapshot, encoded)); err == nil {
		t.Fatal("Layout authoring authority was accepted under a pre-v20 Catalog schema")
	}

	snapshot := mustOpenSnapshot(t, snapshotArtifact)
	viewArtifact, err := ProjectRuntimeMetadataView(snapshot, ProjectionKey{
		AppInstallationID: testInstallA, CapabilityID: layoutauthoringv1.CapabilityName,
	})
	if err != nil {
		t.Fatal(err)
	}
	var viewDoc runtimeViewDocument
	if err := json.Unmarshal(viewArtifact.Bytes(), &viewDoc); err != nil {
		t.Fatal(err)
	}
	viewDoc.Schema = RuntimeMetadataViewSchemaV26
	encoded, err = marshalCanonical(viewDoc)
	if err != nil {
		t.Fatal(err)
	}
	if _, err := OpenRuntimeMetadataView(makeArtifact(ArtifactRuntimeMetadataView, encoded)); err == nil {
		t.Fatal("Layout authoring authority was accepted under a pre-v27 Runtime view schema")
	}
}

func TestLayoutAuthoringCatalogSchemaDoesNotBroadenOtherRuntimeProfiles(t *testing.T) {
	input := layoutAuthoringCompileInput()
	input.Projections = append(input.Projections, RuntimeProjectionInput{
		CatalogRevision: testRevision, AppInstallationID: testInstallB,
		CapabilityID: testCapability, Profile: ProjectionSelectedRootReadV1,
		ObjectAPINames: []string{"WorkItem", "Workspace"},
	})
	snapshot := mustOpenSnapshot(t, mustCompile(t, input))
	artifact, err := ProjectRuntimeMetadataView(snapshot, ProjectionKey{
		AppInstallationID: testInstallB, CapabilityID: testCapability,
	})
	if err != nil {
		t.Fatal(err)
	}
	view := mustOpenView(t, artifact)
	if view.doc.Schema != RuntimeMetadataViewSchemaV4 || view.doc.LayoutAuthoring != nil || len(view.Objects()) == 0 {
		t.Fatalf("unrelated Runtime profile inherited Layout authority: schema=%q authoring=%t objects=%d",
			view.doc.Schema, view.doc.LayoutAuthoring != nil, len(view.Objects()))
	}
}

func TestLayoutAuthoringVersionsCoverDocumentListFieldsAndRouting(t *testing.T) {
	baselineInput := layoutAuthoringCompileInput()
	baseline := projectLayoutAuthoringViewForTest(t, baselineInput)
	baselineStored, _ := baseline.LayoutAuthoringStoredLayout("layout-work-item")
	baselineWorkspace, _ := baseline.LayoutAuthoringWorkspace("WorkItem")
	computed, err := ComputeLayoutAuthoringVersions(
		"WorkItem", []string{"Subject", "Done"},
		layoutAuthoringAggregateForTest(&baselineInput, "WorkItem").Layouts,
		layoutAuthoringAggregateForTest(&baselineInput, "WorkItem").Assignments,
	)
	if err != nil {
		t.Fatal(err)
	}
	if computed.WorkspaceVersion != baselineWorkspace.WorkspaceVersion ||
		computed.LayoutResourceVersions["layout-work-item"] != baselineStored.ResourceVersion ||
		computed.LayoutAggregateVersions["layout-work-item"] != baselineStored.AggregateVersion ||
		computed.AssignmentResourceVersions["assignment-default"] != baselineWorkspace.Assignments[0].ResourceVersion {
		t.Fatalf("locked aggregate versions diverged from Catalog projection: %#v", computed)
	}

	documentChanged := layoutAuthoringCompileInput()
	layoutAuthoringAggregateForTest(&documentChanged, "WorkItem").Layouts[0].Sections[0].Label = "Changed"
	changedDocument := projectLayoutAuthoringViewForTest(t, documentChanged)
	changedStored, _ := changedDocument.LayoutAuthoringStoredLayout("layout-work-item")
	if changedStored.ResourceVersion == baselineStored.ResourceVersion ||
		changedStored.AggregateVersion == baselineStored.AggregateVersion ||
		changedStored.WorkspaceVersion == baselineStored.WorkspaceVersion {
		t.Fatal("document mutation did not reach every owning version")
	}

	listChanged := layoutAuthoringCompileInput()
	layoutAuthoringAggregateForTest(&listChanged, "WorkItem").OrderedListFields = []string{"Done", "Subject"}
	changedList := projectLayoutAuthoringViewForTest(t, listChanged)
	listStored, _ := changedList.LayoutAuthoringStoredLayout("layout-work-item")
	if listStored.ResourceVersion != baselineStored.ResourceVersion ||
		listStored.AggregateVersion == baselineStored.AggregateVersion ||
		listStored.WorkspaceVersion == baselineStored.WorkspaceVersion {
		t.Fatal("ListFields mutation reached the wrong version boundary")
	}

	routingChanged := layoutAuthoringCompileInput()
	profile := "profile-sales"
	routingAggregate := layoutAuthoringAggregateForTest(&routingChanged, "WorkItem")
	routingAggregate.Assignments[0].ProfileID = &profile
	routingAggregate.Assignments[0].Specificity = 1
	routingAggregate.Layouts[0].IsDefault = false
	changedRouting := projectLayoutAuthoringViewForTest(t, routingChanged)
	routingStored, _ := changedRouting.LayoutAuthoringStoredLayout("layout-work-item")
	routingWorkspace, _ := changedRouting.LayoutAuthoringWorkspace("WorkItem")
	if routingStored.ResourceVersion == baselineStored.ResourceVersion ||
		routingStored.AggregateVersion != baselineStored.AggregateVersion ||
		routingWorkspace.WorkspaceVersion == baselineWorkspace.WorkspaceVersion ||
		routingWorkspace.Assignments[0].Specificity != 1 {
		t.Fatal("routing mutation reached the wrong boundary or trusted stale specificity")
	}
}

func TestLayoutAuthoringProjectionRejectsMixedRevisionAndDerivesDefaultFromWildcard(t *testing.T) {
	t.Run("mixed revision", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		input.LayoutAuthoringAggregates[0].CatalogRevision++
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("mixed-revision stored Layout compiled")
		}
	})
	t.Run("raw default without wildcard is ignored", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		layoutAuthoringAggregateForTest(&input, "WorkItem").Assignments = []*models.LayoutAssignment{}
		view := projectLayoutAuthoringViewForTest(t, input)
		workspace, ok := view.LayoutAuthoringWorkspace("WorkItem")
		if !ok || len(workspace.Layouts) != 1 || workspace.Layouts[0].IsDefault {
			t.Fatalf("raw default leaked into authoring projection: %#v", workspace)
		}
	})
	t.Run("wildcard overrides a false raw default", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		layoutAuthoringAggregateForTest(&input, "WorkItem").Layouts[0].IsDefault = false
		view := projectLayoutAuthoringViewForTest(t, input)
		workspace, ok := view.LayoutAuthoringWorkspace("WorkItem")
		if !ok || len(workspace.Layouts) != 1 || !workspace.Layouts[0].IsDefault {
			t.Fatalf("wildcard default was not projected: %#v", workspace)
		}
	})
	t.Run("negative stored version", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		layoutAuthoringAggregateForTest(&input, "WorkItem").Layouts[0].LayoutVersion = -1
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("negative stored Layout version was silently normalized")
		}
	})
	t.Run("overflowing stored order", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		layoutAuthoringAggregateForTest(&input, "WorkItem").Layouts[0].RecordPanels[0].Order = int(^uint32(0))
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("overflowing stored panel order was silently truncated")
		}
	})
	t.Run("profile bound to another capability", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		input.Projections[0].CapabilityID = "runtime.unrelated.v1"
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("Layout authoring profile compiled under another capability")
		}
	})
}

func TestLayoutAuthoringProjectionRequiresCanonicalObjectIdentity(t *testing.T) {
	// Historical spelling is resolved by the stored aggregate reader, not by
	// the immutable Catalog compiler or its version/digest checks.
	for name, mutate := range map[string]func(*models.LayoutAuthoringAggregate){
		"object":     func(value *models.LayoutAuthoringAggregate) { value.ObjectAPIName = "workitem" },
		"layout":     func(value *models.LayoutAuthoringAggregate) { value.Layouts[0].ObjectAPIName = "workitem" },
		"assignment": func(value *models.LayoutAuthoringAggregate) { value.Assignments[0].ObjectAPIName = "workitem" },
	} {
		t.Run(name, func(t *testing.T) {
			input := layoutAuthoringCompileInput()
			mutate(layoutAuthoringAggregateForTest(&input, "WorkItem"))
			if _, err := CompileCatalogSnapshot(input); err == nil {
				t.Fatal("Catalog accepted a noncanonical object identity instead of exact aggregate facts")
			}
		})
	}
}

func TestLayoutAuthoringAssignmentFactsAreNotNormalizedAndUseContractOrdering(t *testing.T) {
	t.Run("empty selector fails closed", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		empty := ""
		assignment := layoutAuthoringAggregateForTest(&input, "WorkItem").Assignments[0]
		assignment.ProfileID = &empty
		assignment.Specificity = 1
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("present-empty stored selector was silently normalized")
		}
	})
	t.Run("stored specificity must match selectors", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		layoutAuthoringAggregateForTest(&input, "WorkItem").Assignments[0].Specificity = 1
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("drifted stored specificity compiled")
		}
	})
	t.Run("assignment ids are bytewise ordered", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		aggregate := layoutAuthoringAggregateForTest(&input, "WorkItem")
		aggregate.Assignments[0].ID = "a"
		profile := "profile-1"
		aggregate.Assignments = append(aggregate.Assignments,
			&models.LayoutAssignment{
				ID: "Z", ObjectAPIName: "WorkItem", LayoutID: "layout-work-item",
				ProfileID: &profile, Specificity: 1,
			},
		)
		view := projectLayoutAuthoringViewForTest(t, input)
		workspace, ok := view.LayoutAuthoringWorkspace("WorkItem")
		if !ok || len(workspace.Assignments) != 2 || workspace.Assignments[0].AssignmentID != "Z" || workspace.Assignments[1].AssignmentID != "a" {
			t.Fatalf("assignment order = %#v, want Z then a", workspace.Assignments)
		}
	})
}

func TestLayoutInputsRequireAnOwningProjection(t *testing.T) {
	t.Run("stored authoring aggregates", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		input.Projections = nil
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("unowned stored Layout aggregates compiled")
		}
	})
	t.Run("caller-effective resolution facts", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		input.Projections = nil
		input.LayoutAuthoringAggregates = nil
		input.PageLayoutRecordTypes = []PageLayoutRecordTypeInput{{CatalogRevision: testRevision, ObjectAPIName: "WorkItem", RecordTypeID: "rt-1"}}
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("unowned page-layout resolution facts compiled")
		}
	})
	t.Run("authoring cannot consume resolution inputs", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		aggregate := layoutAuthoringAggregateForTest(&input, "WorkItem")
		input.PageLayouts = []PageLayoutInput{{CatalogRevision: testRevision, Layout: aggregate.Layouts[0]}}
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("caller-effective Layout facts entered an authoring-only compilation")
		}
	})
	t.Run("resolution cannot consume authoring inputs", func(t *testing.T) {
		input := pageLayoutResolutionCompileInput()
		input.LayoutAuthoringAggregates = layoutAuthoringCompileInput().LayoutAuthoringAggregates
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("stored Layout aggregates entered a resolution-only compilation")
		}
	})
}

func TestLayoutAuthoringAggregateInputIsCompleteAndObjectScoped(t *testing.T) {
	t.Run("missing object aggregate", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		input.LayoutAuthoringAggregates = input.LayoutAuthoringAggregates[:len(input.LayoutAuthoringAggregates)-1]
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("incomplete stored Layout workspace set compiled")
		}
	})
	t.Run("nil collection", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		layoutAuthoringAggregateForTest(&input, "WorkItem").Layouts = nil
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("nil stored Layout collection compiled as empty")
		}
	})
	t.Run("foreign Layout", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		layoutAuthoringAggregateForTest(&input, "WorkItem").Layouts[0].ObjectAPIName = "Unrelated"
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("foreign Layout escaped its stored aggregate")
		}
	})
	t.Run("foreign assignment", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		layoutAuthoringAggregateForTest(&input, "WorkItem").Assignments[0].ObjectAPIName = "Unrelated"
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("foreign assignment escaped its stored aggregate")
		}
	})
}

func TestLayoutAuthoringProjectionDoesNotRequireCallerEffectiveRoutingClosure(t *testing.T) {
	input := layoutAuthoringCompileInput()
	aggregate := layoutAuthoringAggregateForTest(&input, "WorkItem")
	aggregate.Layouts[0].IsDefault = false
	aggregate.Assignments = []*models.LayoutAssignment{}
	input.PageLayoutRecordTypes = nil
	artifact, err := CompileCatalogSnapshot(input)
	if err != nil {
		t.Fatalf("valid unassigned authoring workspace was coupled to page-layout resolution: %v", err)
	}
	if mustOpenSnapshot(t, artifact).doc.LayoutAuthoring == nil {
		t.Fatal("authoring projection is absent")
	}
}

func TestLayoutAuthoringAndResolutionConsumeDistinctFactsFromOneRevision(t *testing.T) {
	input := layoutAuthoringCompileInput()
	aggregate := layoutAuthoringAggregateForTest(&input, "WorkItem")
	legacyCreate := *aggregate.Layouts[0]
	legacyCreate.ID = "layout-legacy-create"
	legacyCreate.LayoutName = "Legacy Create"
	legacyCreate.Type = "Create"
	legacyCreate.IsDefault = false
	aggregate.Layouts = append(aggregate.Layouts, &legacyCreate)

	// Caller-effective resolution deliberately receives only its eligible
	// subset. The complete stored aggregate above remains independently owned
	// by the authoring projection even when both views share one revision.
	input.PageLayouts = []PageLayoutInput{{CatalogRevision: testRevision, Layout: aggregate.Layouts[0]}}
	input.LayoutAssignments = []LayoutAssignmentInput{{CatalogRevision: testRevision, Assignment: aggregate.Assignments[0]}}
	input.Projections = append(input.Projections, RuntimeProjectionInput{
		CatalogRevision: testRevision, AppInstallationID: testInstallB,
		CapabilityID: "runtime.metadata.resolve-page-layout.v1", Profile: ProjectionPageLayoutResolutionV1,
		ObjectAPINames: []string{"WorkItem"},
	})

	snapshot := mustOpenSnapshot(t, mustCompile(t, input))
	if len(snapshot.doc.PageLayoutResolution.Layouts) != 1 ||
		snapshot.doc.PageLayoutResolution.Layouts[0].ID != "layout-work-item" {
		t.Fatalf("caller-effective resolution facts = %#v", snapshot.doc.PageLayoutResolution.Layouts)
	}
	authoringArtifact, err := ProjectRuntimeMetadataView(snapshot, ProjectionKey{
		AppInstallationID: testInstallA, CapabilityID: layoutauthoringv1.CapabilityName,
	})
	if err != nil {
		t.Fatal(err)
	}
	authoring := mustOpenView(t, authoringArtifact)
	if stored, ok := authoring.LayoutAuthoringStoredLayout("layout-legacy-create"); !ok || stored.Document.Kind != "Create" {
		t.Fatalf("stored Type=Create Layout was not preserved: %#v, found=%t", stored, ok)
	}
}

func TestLayoutAuthoringPreservesAssignedTypeCreateAsStoredFact(t *testing.T) {
	input := layoutAuthoringCompileInput()
	aggregate := layoutAuthoringAggregateForTest(&input, "WorkItem")
	aggregate.Layouts[0].Type = "Create"
	view := projectLayoutAuthoringViewForTest(t, input)
	workspace, ok := view.LayoutAuthoringWorkspace("WorkItem")
	if !ok || len(workspace.Layouts) != 1 || workspace.Layouts[0].Kind != "Create" ||
		len(workspace.Assignments) != 1 || workspace.Assignments[0].LayoutID != workspace.Layouts[0].LayoutID {
		t.Fatalf("assigned Type=Create stored aggregate = %#v", workspace)
	}
}

func TestLayoutAuthoringProjectionRejectsGloballyAmbiguousResourceIdentities(t *testing.T) {
	t.Run("layout", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		duplicate := *layoutAuthoringAggregateForTest(&input, "WorkItem").Layouts[0]
		duplicate.ID = "LAYOUT-WORK-ITEM"
		duplicate.ObjectAPIName = "Unrelated"
		duplicate.LayoutName = "Duplicate"
		duplicate.IsDefault = false
		unrelated := layoutAuthoringAggregateForTest(&input, "Unrelated")
		unrelated.Layouts = append(unrelated.Layouts, &duplicate)
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("globally case-insensitive Layout identity collision compiled")
		}
	})
	t.Run("assignment", func(t *testing.T) {
		input := layoutAuthoringCompileInput()
		aggregate := layoutAuthoringAggregateForTest(&input, "WorkItem")
		duplicate := *aggregate.Assignments[0]
		duplicate.ID = "ASSIGNMENT-DEFAULT"
		aggregate.Assignments = append(aggregate.Assignments, &duplicate)
		if _, err := CompileCatalogSnapshot(input); err == nil {
			t.Fatal("globally case-insensitive assignment identity collision compiled")
		}
	})
}

func TestPlainStoredJSONDecimalExpandsExponentWithoutFloatLoss(t *testing.T) {
	tests := map[string]string{
		"1e+06":            "1000000",
		"1.2300e2":         "123.00",
		"1.2300e-2":        "0.012300",
		"-9.5E-3":          "-0.0095",
		"12.50":            "12.50",
		"9007199254740993": "9007199254740993",
	}
	for input, expected := range tests {
		actual, err := plainStoredJSONDecimal(input)
		if err != nil {
			t.Fatalf("plainStoredJSONDecimal(%q): %v", input, err)
		}
		if actual != expected {
			t.Fatalf("plainStoredJSONDecimal(%q) = %q, want %q", input, actual, expected)
		}
	}
}

func projectLayoutAuthoringViewForTest(t *testing.T, input CompileInput) *RuntimeMetadataView {
	t.Helper()
	snapshot := mustOpenSnapshot(t, mustCompile(t, input))
	artifact, err := ProjectRuntimeMetadataView(snapshot, ProjectionKey{
		AppInstallationID: testInstallA, CapabilityID: layoutauthoringv1.CapabilityName,
	})
	if err != nil {
		t.Fatal(err)
	}
	return mustOpenView(t, artifact)
}

func layoutAuthoringCompileInput() CompileInput {
	input := neutralCompileInput()
	input.Projections = []RuntimeProjectionInput{{
		CatalogRevision: testRevision, AppInstallationID: testInstallA,
		CapabilityID: layoutauthoringv1.CapabilityName, Profile: ProjectionLayoutAuthoringV1,
		ObjectAPINames: []string{"WorkItem"},
	}}
	empty := ""
	condition := "record.Done == false"
	icon := "task"
	now := time.Date(2026, 8, 30, 10, 0, 0, 123000000, time.UTC)
	layout := &models.PageLayout{
		ID: "layout-work-item", ObjectAPIName: "WorkItem", LayoutName: "Work Item", Type: "Detail",
		IsDefault: true, CompactLayout: []string{"Subject"}, Tabs: []string{"main"},
		Sections: []models.PageSection{{
			ID: "section-main", Label: "Main", Tab: &empty, Type: nil, ComponentName: &empty,
			ComponentConfig: map[string]interface{}{"enabled": true, "nested": map[string]interface{}{"n": float64(2)}},
			Columns:         2, Fields: []string{"Subject", "WorkspaceId.Name"},
			FieldLabels: map[string]string{"Orphaned": "Preserved", "Subject": "Subject override"},
			FieldBehaviors: map[string]map[string]string{
				"Done": {}, "NilFact": nil, "Subject": {"Create": "  Required  "},
			},
			VisibilityCondition: &condition,
		}},
		RelatedLists: []models.RelatedListConfig{{
			ID: "related-unrelated", Label: "Related", ObjectAPIName: "Unrelated", LookupField: "WorkItemId",
			Fields: []string{"Id"}, PrefillMappings: map[string]string{"WorkItemId": "Id"},
		}},
		RecordPanels: []models.RecordPanelConfig{{
			ID: "panel-a", RendererID: "renderer-a", Position: "tab", TabID: "main", TabLabel: "Panel",
			Config: map[string]interface{}{"mode": "full"},
		}},
		HeaderActions: []models.ActionConfig{{
			Name: "save", Label: "Save", Type: "Standard", Icon: &icon,
			Config: map[string]interface{}{
				"confirm": false, "threshold": json.Number("12.50"),
				"nested": map[string]interface{}{"large": json.Number("9007199254740993")},
			},
			Extensions: map[string]interface{}{"description": "Save this record"},
		}},
		QuickActions: []models.ActionConfig{}, HeaderActionsAuthored: true, QuickActionsAuthored: true,
		RecordStates: []models.RecordStateRule{{
			ID: "open", When: "Done == false", Banner: &models.RecordStateBanner{
				Severity: "info", Title: "Open", LinkIDs: []string{"workspace"},
			},
			Links: []models.RecordStateLink{{
				ID: "workspace", Label: "Workspace", ReferenceFieldAPIName: "WorkspaceId", ObjectAPIName: "Workspace", Placement: "banner",
			}},
			ActionOverrides: []models.RecordStateActionOverride{{ActionKey: "delete", Mode: "disable", Reason: "Open"}},
			ReadOnly:        &models.RecordStateReadOnly{Enabled: true, Reason: "Open"},
		}},
		PrimaryHeaderActions: []string{"save"}, Source: "admin_created", IsCustomized: true,
		CreatedDate: now.Add(-time.Hour), LastModifiedDate: now,
	}
	actor := "user-1"
	assignment := &models.LayoutAssignment{
		ID: "assignment-default", ObjectAPIName: "WorkItem", LayoutID: "layout-work-item",
		CreatedByID: &actor, CreatedDate: now.Add(-time.Hour), LastModifiedDate: now,
	}
	for _, object := range input.Objects {
		aggregate := &models.LayoutAuthoringAggregate{
			ObjectAPIName: object.Metadata.APIName, OrderedListFields: []string{},
			Layouts: []*models.PageLayout{}, Assignments: []*models.LayoutAssignment{},
		}
		if object.Metadata.APIName == "WorkItem" {
			aggregate.OrderedListFields = []string{"Subject", "Done"}
			aggregate.Layouts = []*models.PageLayout{layout}
			aggregate.Assignments = []*models.LayoutAssignment{assignment}
		}
		input.LayoutAuthoringAggregates = append(input.LayoutAuthoringAggregates, LayoutAuthoringAggregateInput{
			CatalogRevision: testRevision, Aggregate: aggregate,
		})
	}
	return input
}

func layoutAuthoringAggregateForTest(input *CompileInput, objectID string) *models.LayoutAuthoringAggregate {
	for index := range input.LayoutAuthoringAggregates {
		aggregate := input.LayoutAuthoringAggregates[index].Aggregate
		if aggregate != nil && aggregate.ObjectAPIName == objectID {
			return aggregate
		}
	}
	panic("Layout authoring aggregate is absent: " + objectID)
}

func layoutAuthoringNamedValue(t *testing.T, values []layoutauthoringv1.NamedValue, name string) layoutauthoringv1.NamedValue {
	t.Helper()
	for _, value := range values {
		if value.Name == name {
			return value
		}
	}
	t.Fatalf("named value %q is absent from %#v", name, values)
	return layoutauthoringv1.NamedValue{}
}

func layoutAuthoringStringPointer(value string) *string { return &value }
