package packs

import (
	"testing"
)

// TestBuildObjectMetadataIndexUnionsDuplicateAPINames verifies that when two
// ObjectSpecs share the same APIName (a real scenario for split-spec objects),
// BuildObjectMetadataIndex produces a single entry whose Fields slice is the
// union of both specs' fields — mirroring buildFlowObjectFieldGraph semantics.
func TestBuildObjectMetadataIndexUnionsDuplicateAPINames(t *testing.T) {
	specs := []ObjectSpec{
		{
			APIName: "Account",
			Fields: []FieldSpec{
				{APIName: "Name", Type: "string"},
				{APIName: "Industry", Type: "string"},
			},
		},
		{
			APIName: "Account", // same APIName — different fields
			Fields: []FieldSpec{
				{APIName: "Industry", Type: "string"},    // duplicate — must not be doubled
				{APIName: "AnnualRevenue", Type: "double"},
			},
		},
	}

	index := BuildObjectMetadataIndex(specs)

	entry := index["account"]
	if entry == nil {
		t.Fatal("BuildObjectMetadataIndex: expected entry for 'account', got nil")
	}

	fieldSet := make(map[string]bool, len(entry.Fields))
	for _, f := range entry.Fields {
		fieldSet[f.APIName] = true
	}

	// Field from first spec must be present.
	if !fieldSet["Name"] {
		t.Error("union entry missing 'Name' field from first spec")
	}
	// Field from second spec (not in first) must be present.
	if !fieldSet["AnnualRevenue"] {
		t.Error("union entry missing 'AnnualRevenue' field from second spec")
	}
	// Duplicate field 'Industry' must appear exactly once.
	count := 0
	for _, f := range entry.Fields {
		if f.APIName == "Industry" {
			count++
		}
	}
	if count != 1 {
		t.Errorf("union entry has 'Industry' %d times; want exactly 1", count)
	}
}

// TestBuildObjectMetadataIndexDoesNotMutateInputs verifies that
// unionObjectMetadataFields does not mutate the original ObjectMetadata
// values returned by buildObjectMetadata (immutability requirement).
func TestBuildObjectMetadataIndexDoesNotMutateInputs(t *testing.T) {
	specs := []ObjectSpec{
		{
			APIName: "Contact",
			Fields: []FieldSpec{
				{APIName: "FirstName", Type: "string"},
			},
		},
		{
			APIName: "Contact",
			Fields: []FieldSpec{
				{APIName: "LastName", Type: "string"},
			},
		},
	}

	origObjects := buildObjectMetadata(specs)
	origLens := make([]int, len(origObjects))
	for i, o := range origObjects {
		if o != nil {
			origLens[i] = len(o.Fields)
		}
	}

	BuildObjectMetadataIndex(specs)

	// Verify the original ObjectMetadata structs were not mutated.
	for i, o := range origObjects {
		if o != nil && len(o.Fields) != origLens[i] {
			t.Errorf("buildObjectMetadata result[%d] Fields length mutated from %d to %d", i, origLens[i], len(o.Fields))
		}
	}
}
