package layoutbundleownerverificationv1

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"math"
	"reflect"
	"strings"
	"testing"

	"github.com/pingcap-inc/nexuscrm-contract/pkg/layoutbundlekeyv1"
)

const receiptTestWriterCommandID = "0190d800-0000-7000-8000-000000000123"

func TestValueSurfaceAndConstantsAreExact(t *testing.T) {
	assertExactFields(t, reflect.TypeOf(Receipt{}), []fieldExpectation{
		{"ReceiptVersion", reflect.TypeOf("")},
		{"OrgID", reflect.TypeOf("")},
		{"WriterCommandID", reflect.TypeOf("")},
		{"WriterReservationGeneration", reflect.TypeOf(uint64(0))},
		{"SourceRequestDigest", reflect.TypeOf("")},
		{"RequiredBundleKeySetDigest", reflect.TypeOf("")},
		{"BundleKey", reflect.TypeOf(layoutbundlekeyv1.BundleKey{})},
		{"EvidenceVersion", reflect.TypeOf("")},
		{"EvidenceDigest", reflect.TypeOf("")},
		{"VerificationState", reflect.TypeOf(VerificationState(0))},
	})
	assertExactFields(t, reflect.TypeOf(ReceiptEntry{}), []fieldExpectation{
		{"BundleKey", reflect.TypeOf(layoutbundlekeyv1.BundleKey{})},
		{"EvidenceVersion", reflect.TypeOf("")},
		{"EvidenceDigest", reflect.TypeOf("")},
		{"VerificationState", reflect.TypeOf(VerificationState(0))},
	})
	assertExactFields(t, reflect.TypeOf(ReceiptSet{}), []fieldExpectation{
		{"ReceiptSetVersion", reflect.TypeOf("")},
		{"ReceiptVersion", reflect.TypeOf("")},
		{"OrgID", reflect.TypeOf("")},
		{"WriterCommandID", reflect.TypeOf("")},
		{"WriterReservationGeneration", reflect.TypeOf(uint64(0))},
		{"SourceRequestDigest", reflect.TypeOf("")},
		{"RequiredBundleKeySetDigest", reflect.TypeOf("")},
		{"Receipts", reflect.TypeOf([]ReceiptEntry{})},
	})

	if ReceiptVersion != "nexuscrm.layout-bundle-owner-verification-receipt/v1" {
		t.Fatalf("ReceiptVersion = %q", ReceiptVersion)
	}
	if ReceiptSetVersion != "nexuscrm.layout-bundle-owner-verification-receipt-set/v1" {
		t.Fatalf("ReceiptSetVersion = %q", ReceiptSetVersion)
	}
	if VerificationStateVerified != 0x01 {
		t.Fatalf("VerificationStateVerified = %#x", VerificationStateVerified)
	}
	if MaxReceipts != 100_000 || MaxCanonicalReceiptSetBytes != 32_505_856 {
		t.Fatalf("limits = %d/%d", MaxReceipts, MaxCanonicalReceiptSetBytes)
	}
}

func TestValidateReceiptAcceptsEveryOwnerAndRejectsForeignEvidenceVersions(t *testing.T) {
	for _, kind := range []layoutbundlekeyv1.SlotOwnerKind{
		layoutbundlekeyv1.SlotOwnerKindApp,
		layoutbundlekeyv1.SlotOwnerKindTenant,
		layoutbundlekeyv1.SlotOwnerKindSystem,
	} {
		t.Run(string(kind), func(t *testing.T) {
			receipt := validReceipt(kind)
			if err := ValidateReceipt(receipt); err != nil {
				t.Fatalf("ValidateReceipt: %v", err)
			}
			if _, err := CanonicalReceiptBytes(receipt); err != nil {
				t.Fatalf("CanonicalReceiptBytes: %v", err)
			}
			if _, err := ReceiptDigest(receipt); err != nil {
				t.Fatalf("ReceiptDigest: %v", err)
			}

			receipt.EvidenceVersion = evidenceVersionForDifferentOwner(kind)
			assertReceiptErrorContains(t, receipt, "EvidenceVersion")
		})
	}
}

func TestValidateReceiptRejectsInvalidEnvelopeKeyDigestAndClosedState(t *testing.T) {
	tests := map[string]struct {
		mutate func(*Receipt)
		want   string
	}{
		"receipt version": {
			mutate: func(receipt *Receipt) { receipt.ReceiptVersion = "v2" },
			want:   "ReceiptVersion",
		},
		"empty org": {
			mutate: func(receipt *Receipt) { receipt.OrgID = "" },
			want:   "OrgID",
		},
		"org leading space": {
			mutate: func(receipt *Receipt) { receipt.OrgID = " org" },
			want:   "OrgID",
		},
		"org trailing space": {
			mutate: func(receipt *Receipt) { receipt.OrgID = "org " },
			want:   "OrgID",
		},
		"org control": {
			mutate: func(receipt *Receipt) { receipt.OrgID = "org\nother" },
			want:   "OrgID",
		},
		"org DEL": {
			mutate: func(receipt *Receipt) { receipt.OrgID = "org\x7fother" },
			want:   "OrgID",
		},
		"org invalid UTF-8": {
			mutate: func(receipt *Receipt) { receipt.OrgID = string([]byte{0xff}) },
			want:   "OrgID",
		},
		"org over limit": {
			mutate: func(receipt *Receipt) { receipt.OrgID = strings.Repeat("o", 256) },
			want:   "OrgID",
		},
		"uppercase command": {
			mutate: func(receipt *Receipt) { receipt.WriterCommandID = strings.ToUpper(receipt.WriterCommandID) },
			want:   "UUIDv7",
		},
		"wrong command version": {
			mutate: func(receipt *Receipt) { receipt.WriterCommandID = "0190d800-0000-6000-8000-000000000123" },
			want:   "UUIDv7",
		},
		"wrong command variant": {
			mutate: func(receipt *Receipt) { receipt.WriterCommandID = "0190d800-0000-7000-7000-000000000123" },
			want:   "UUIDv7",
		},
		"zero writer generation": {
			mutate: func(receipt *Receipt) { receipt.WriterReservationGeneration = 0 },
			want:   "positive",
		},
		"source digest": {
			mutate: func(receipt *Receipt) { receipt.SourceRequestDigest = receiptTestDigest('A') },
			want:   "lowercase",
		},
		"required digest": {
			mutate: func(receipt *Receipt) { receipt.RequiredBundleKeySetDigest = "sha256:bad" },
			want:   "sha256",
		},
		"bundle key": {
			mutate: func(receipt *Receipt) { receipt.BundleKey.LocalComponentKey = "key256:bad" },
			want:   "BundleKey",
		},
		"evidence digest": {
			mutate: func(receipt *Receipt) { receipt.EvidenceDigest = receiptTestDigest('G') },
			want:   "EvidenceDigest",
		},
		"unverified zero tag": {
			mutate: func(receipt *Receipt) { receipt.VerificationState = 0x00 },
			want:   "VERIFIED",
		},
		"unknown tag": {
			mutate: func(receipt *Receipt) { receipt.VerificationState = 0x02 },
			want:   "VERIFIED",
		},
	}
	for name, test := range tests {
		t.Run(name, func(t *testing.T) {
			receipt := validReceipt(layoutbundlekeyv1.SlotOwnerKindApp)
			test.mutate(&receipt)
			assertReceiptErrorContains(t, receipt, test.want)
		})
	}

	receipt := validReceipt(layoutbundlekeyv1.SlotOwnerKindTenant)
	receipt.OrgID = strings.Repeat("界", 85)
	if len(receipt.OrgID) != 255 {
		t.Fatalf("UTF-8 OrgID bytes = %d", len(receipt.OrgID))
	}
	if err := ValidateReceipt(receipt); err != nil {
		t.Fatalf("255-byte UTF-8 OrgID rejected: %v", err)
	}
}

func TestReceiptSetRequiresExplicitCompleteRequiredKeyClosure(t *testing.T) {
	set, required := validReceiptSet(t)
	if err := ValidateReceiptSet(set, required); err != nil {
		t.Fatalf("ValidateReceiptSet: %v", err)
	}

	nilReceipts := set
	nilReceipts.Receipts = nil
	assertReceiptSetErrorContains(t, nilReceipts, required, "must be present")

	emptyRequired := layoutbundlekeyv1.RequiredBundleKeySet{
		Version:    layoutbundlekeyv1.RequiredBundleKeySetVersion,
		BundleKeys: []layoutbundlekeyv1.BundleKey{},
	}
	emptyDigest, err := layoutbundlekeyv1.RequiredBundleKeySetDigest(emptyRequired)
	if err != nil {
		t.Fatal(err)
	}
	empty := set
	empty.RequiredBundleKeySetDigest = emptyDigest
	empty.Receipts = []ReceiptEntry{}
	if err := ValidateReceiptSet(empty, emptyRequired); err != nil {
		t.Fatalf("explicit empty receipt set rejected: %v", err)
	}
	if _, err := CanonicalReceiptSetBytes(empty, emptyRequired); err != nil {
		t.Fatalf("canonical empty receipt set rejected: %v", err)
	}
	assertReceiptSetErrorContains(t, empty, required, "does not match")

	duplicate := set
	duplicate.Receipts = append([]ReceiptEntry{}, set.Receipts...)
	duplicate.Receipts[1].BundleKey = duplicate.Receipts[0].BundleKey
	assertReceiptSetErrorContains(t, duplicate, required, "duplicate BundleKey")

	missing := set
	missing.Receipts = append([]ReceiptEntry{}, set.Receipts[:len(set.Receipts)-1]...)
	assertReceiptSetErrorContains(t, missing, required, "exactly one")

	extra := set
	extra.Receipts = append([]ReceiptEntry{}, set.Receipts...)
	extra.Receipts[0].BundleKey = layoutbundlekeyv1.BundleKey{
		SlotOwnerKind:      layoutbundlekeyv1.SlotOwnerKindTenant,
		SlotOwnerNamespace: "io.example.extra",
		LocalComponentKey:  receiptTestLocalKey('e'),
	}
	extra.Receipts[0].EvidenceVersion = TenantAuthorityEvidenceVersion
	assertReceiptSetErrorContains(t, extra, required, "not a required BundleKey")

	sourceMismatch := set
	sourceMismatch.RequiredBundleKeySetDigest = receiptTestDigest('f')
	assertReceiptSetErrorContains(t, sourceMismatch, required, "does not match")
}

func TestValidateReceiptSetRejectsInvalidSharedEnvelope(t *testing.T) {
	tests := map[string]struct {
		mutate func(*ReceiptSet)
		want   string
	}{
		"set version": {
			mutate: func(set *ReceiptSet) { set.ReceiptSetVersion = "v2" },
			want:   "ReceiptSetVersion",
		},
		"receipt version": {
			mutate: func(set *ReceiptSet) { set.ReceiptVersion = "v2" },
			want:   "ReceiptVersion",
		},
		"org": {
			mutate: func(set *ReceiptSet) { set.OrgID = "" },
			want:   "OrgID",
		},
		"writer command": {
			mutate: func(set *ReceiptSet) { set.WriterCommandID = "0190d800-0000-6000-8000-000000000123" },
			want:   "UUIDv7",
		},
		"writer generation": {
			mutate: func(set *ReceiptSet) { set.WriterReservationGeneration = 0 },
			want:   "positive",
		},
		"source digest": {
			mutate: func(set *ReceiptSet) { set.SourceRequestDigest = "sha256:bad" },
			want:   "SourceRequestDigest",
		},
		"required digest": {
			mutate: func(set *ReceiptSet) { set.RequiredBundleKeySetDigest = receiptTestDigest('A') },
			want:   "lowercase",
		},
	}
	for name, test := range tests {
		t.Run(name, func(t *testing.T) {
			set, required := validReceiptSet(t)
			test.mutate(&set)
			assertReceiptSetErrorContains(t, set, required, test.want)
		})
	}
}

func TestReceiptSetCanonicalizationIsPermutationInvariantAndDefensive(t *testing.T) {
	set, required := validReceiptSet(t)
	canonical, err := CanonicalizeReceiptSet(set, required)
	if err != nil {
		t.Fatal(err)
	}
	if got := []layoutbundlekeyv1.SlotOwnerKind{
		canonical.Receipts[0].BundleKey.SlotOwnerKind,
		canonical.Receipts[1].BundleKey.SlotOwnerKind,
		canonical.Receipts[2].BundleKey.SlotOwnerKind,
	}; !reflect.DeepEqual(got, []layoutbundlekeyv1.SlotOwnerKind{
		layoutbundlekeyv1.SlotOwnerKindApp,
		layoutbundlekeyv1.SlotOwnerKindTenant,
		layoutbundlekeyv1.SlotOwnerKindSystem,
	}) {
		t.Fatalf("canonical owner order = %v", got)
	}
	canonical.Receipts[0].EvidenceDigest = receiptTestDigest('f')
	if set.Receipts[2].EvidenceDigest == canonical.Receipts[0].EvidenceDigest {
		t.Fatal("CanonicalizeReceiptSet returned shared receipt storage")
	}

	leftBytes, err := CanonicalReceiptSetBytes(set, required)
	if err != nil {
		t.Fatal(err)
	}
	leftDigest, err := ReceiptSetDigest(set, required)
	if err != nil {
		t.Fatal(err)
	}
	permuted := set
	permuted.Receipts = []ReceiptEntry{set.Receipts[1], set.Receipts[2], set.Receipts[0]}
	rightBytes, err := CanonicalReceiptSetBytes(permuted, required)
	if err != nil {
		t.Fatal(err)
	}
	rightDigest, err := ReceiptSetDigest(permuted, required)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(leftBytes, rightBytes) || leftDigest != rightDigest {
		t.Fatalf("permutation changed canonical identity: %x/%s != %x/%s", leftBytes, leftDigest, rightBytes, rightDigest)
	}
}

func TestReceiptSetCanonicalizationUsesUnsignedRawNamespaceAndLocalKeyBytes(t *testing.T) {
	keys := []layoutbundlekeyv1.BundleKey{
		{
			SlotOwnerKind:      layoutbundlekeyv1.SlotOwnerKindTenant,
			SlotOwnerNamespace: "io.example.v2",
			LocalComponentKey:  receiptTestLocalKey('1'),
		},
		{
			SlotOwnerKind:      layoutbundlekeyv1.SlotOwnerKindTenant,
			SlotOwnerNamespace: "io.example.v10",
			LocalComponentKey:  receiptTestLocalKey('3'),
		},
		{
			SlotOwnerKind:      layoutbundlekeyv1.SlotOwnerKindTenant,
			SlotOwnerNamespace: "io.example.v10",
			LocalComponentKey:  receiptTestLocalKey('2'),
		},
	}
	required := layoutbundlekeyv1.RequiredBundleKeySet{
		Version:    layoutbundlekeyv1.RequiredBundleKeySetVersion,
		BundleKeys: append([]layoutbundlekeyv1.BundleKey{}, keys...),
	}
	requiredDigest, err := layoutbundlekeyv1.RequiredBundleKeySetDigest(required)
	if err != nil {
		t.Fatal(err)
	}
	set, _ := validReceiptSet(t)
	set.RequiredBundleKeySetDigest = requiredDigest
	set.Receipts = []ReceiptEntry{
		receiptEntry(keys[0]),
		receiptEntry(keys[1]),
		receiptEntry(keys[2]),
	}
	canonical, err := CanonicalizeReceiptSet(set, required)
	if err != nil {
		t.Fatal(err)
	}
	got := []layoutbundlekeyv1.BundleKey{
		canonical.Receipts[0].BundleKey,
		canonical.Receipts[1].BundleKey,
		canonical.Receipts[2].BundleKey,
	}
	want := []layoutbundlekeyv1.BundleKey{keys[2], keys[1], keys[0]}
	if !reflect.DeepEqual(got, want) {
		t.Fatalf("raw-byte key order = %#v, want %#v", got, want)
	}
}

func TestReceiptSetReconstructsAndDigestsEverySingularReceipt(t *testing.T) {
	set, required := validReceiptSet(t)
	canonical, err := CanonicalizeReceiptSet(set, required)
	if err != nil {
		t.Fatal(err)
	}
	digests, err := CanonicalReceiptDigests(set, required)
	if err != nil {
		t.Fatal(err)
	}
	if len(digests) != len(canonical.Receipts) {
		t.Fatalf("receipt digest count = %d", len(digests))
	}
	for index, entry := range canonical.Receipts {
		receipt := ReconstructReceipt(canonical, entry)
		if receipt.OrgID != set.OrgID ||
			receipt.WriterCommandID != set.WriterCommandID ||
			receipt.WriterReservationGeneration != set.WriterReservationGeneration ||
			receipt.SourceRequestDigest != set.SourceRequestDigest ||
			receipt.RequiredBundleKeySetDigest != set.RequiredBundleKeySetDigest {
			t.Fatalf("receipt %d does not carry the byte-exact shared source identity", index)
		}
		want, err := ReceiptDigest(receipt)
		if err != nil {
			t.Fatal(err)
		}
		if digests[index] != want {
			t.Fatalf("receipt digest[%d] = %s, want %s", index, digests[index], want)
		}
	}

	mutated := set
	mutated.Receipts = append([]ReceiptEntry{}, set.Receipts...)
	mutated.Receipts[0].EvidenceDigest = receiptTestDigest('f')
	mutatedReceiptDigest, err := ReceiptDigest(ReconstructReceipt(mutated, mutated.Receipts[0]))
	if err != nil {
		t.Fatal(err)
	}
	originalReceiptDigest, err := ReceiptDigest(ReconstructReceipt(set, set.Receipts[0]))
	if err != nil {
		t.Fatal(err)
	}
	if mutatedReceiptDigest == originalReceiptDigest {
		t.Fatal("evidence digest mutation did not change singular receipt digest")
	}
	originalSetDigest, err := ReceiptSetDigest(set, required)
	if err != nil {
		t.Fatal(err)
	}
	mutatedSetDigest, err := ReceiptSetDigest(mutated, required)
	if err != nil {
		t.Fatal(err)
	}
	if mutatedSetDigest == originalSetDigest {
		t.Fatal("evidence digest mutation did not change receipt-set digest")
	}

	mutated.Receipts[0].EvidenceVersion = evidenceVersionForDifferentOwner(mutated.Receipts[0].BundleKey.SlotOwnerKind)
	assertReceiptSetErrorContains(t, mutated, required, "EvidenceVersion")
}

func TestReceiptSetSharedSourceIdentityIsIncludedInSetAndSingularDigests(t *testing.T) {
	set, required := validReceiptSet(t)
	originalSetDigest, err := ReceiptSetDigest(set, required)
	if err != nil {
		t.Fatal(err)
	}
	originalReceiptDigests, err := CanonicalReceiptDigests(set, required)
	if err != nil {
		t.Fatal(err)
	}
	tests := map[string]func(*ReceiptSet){
		"org": func(set *ReceiptSet) {
			set.OrgID = "org-other"
		},
		"writer command": func(set *ReceiptSet) {
			set.WriterCommandID = "0190d800-0000-7000-8000-000000000124"
		},
		"writer generation": func(set *ReceiptSet) {
			set.WriterReservationGeneration++
		},
		"source request digest": func(set *ReceiptSet) {
			set.SourceRequestDigest = receiptTestDigest('d')
		},
	}
	for name, mutate := range tests {
		t.Run(name, func(t *testing.T) {
			changed := set
			mutate(&changed)
			changedSetDigest, err := ReceiptSetDigest(changed, required)
			if err != nil {
				t.Fatal(err)
			}
			changedReceiptDigests, err := CanonicalReceiptDigests(changed, required)
			if err != nil {
				t.Fatal(err)
			}
			if changedSetDigest == originalSetDigest {
				t.Fatal("source identity mutation did not change receipt-set digest")
			}
			if reflect.DeepEqual(changedReceiptDigests, originalReceiptDigests) {
				t.Fatal("source identity mutation did not change reconstructed singular receipt digests")
			}
		})
	}
}

func TestWriterGenerationAndReceiptCountUseMinimalUnsignedLEB128(t *testing.T) {
	for _, test := range []struct {
		generation uint64
		want       []byte
	}{
		{generation: 127, want: []byte{0x7f}},
		{generation: 128, want: []byte{0x80, 0x01}},
		{generation: math.MaxUint64, want: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}},
	} {
		receipt := validReceipt(layoutbundlekeyv1.SlotOwnerKindTenant)
		receipt.WriterReservationGeneration = test.generation
		canonical, err := CanonicalReceiptBytes(receipt)
		if err != nil {
			t.Fatal(err)
		}
		got := receiptGenerationEncoding(t, canonical)
		if !bytes.Equal(got, test.want) {
			t.Fatalf("generation %d encoding = %x, want %x", test.generation, got, test.want)
		}
	}

	for _, count := range []int{127, 128} {
		set, required := receiptCountSet(t, count)
		canonical, err := CanonicalReceiptSetBytes(set, required)
		if err != nil {
			t.Fatal(err)
		}
		got := receiptCountEncoding(t, canonical)
		var encoded [binary.MaxVarintLen64]byte
		length := binary.PutUvarint(encoded[:], uint64(count))
		if !bytes.Equal(got, encoded[:length]) {
			t.Fatalf("count %d encoding = %x, want %x", count, got, encoded[:length])
		}
		if count == 127 && !bytes.Equal(got, []byte{0x7f}) {
			t.Fatalf("count 127 encoding = %x", got)
		}
		if count == 128 && !bytes.Equal(got, []byte{0x80, 0x01}) {
			t.Fatalf("count 128 encoding = %x", got)
		}
	}
}

func TestReceiptSetExactCountAndReachableCanonicalByteBounds(t *testing.T) {
	set, required := exactSizeBoundaryReceiptSet(t)
	size, ok := canonicalReceiptSetSize(set)
	if !ok || size != MaxCanonicalReceiptSetBytes {
		t.Fatalf("boundary size = %d/%t, want %d", size, ok, MaxCanonicalReceiptSetBytes)
	}
	if len(set.Receipts) != MaxReceipts {
		t.Fatalf("boundary receipt count = %d", len(set.Receipts))
	}
	canonical, err := CanonicalReceiptSetBytes(set, required)
	if err != nil {
		t.Fatalf("exact boundary rejected: %v", err)
	}
	if len(canonical) != MaxCanonicalReceiptSetBytes {
		t.Fatalf("canonical boundary bytes = %d", len(canonical))
	}
	digest, err := ReceiptSetDigest(set, required)
	if err != nil {
		t.Fatal(err)
	}
	if digest == "" {
		t.Fatal("boundary digest is empty")
	}

	overflow := set
	overflow.Receipts = append([]ReceiptEntry{}, set.Receipts...)
	overflowRequired := required
	overflowRequired.BundleKeys = append([]layoutbundlekeyv1.BundleKey{}, required.BundleKeys...)
	last := len(overflow.Receipts) - 1
	overflow.Receipts[last].BundleKey.SlotOwnerNamespace = receiptBoundaryNamespace(0, 127)
	overflowRequired.BundleKeys[last] = overflow.Receipts[last].BundleKey
	overflow.RequiredBundleKeySetDigest, err = layoutbundlekeyv1.RequiredBundleKeySetDigest(overflowRequired)
	if err != nil {
		t.Fatal(err)
	}
	overflowSize, ok := canonicalReceiptSetSize(overflow)
	if !ok || overflowSize != MaxCanonicalReceiptSetBytes+1 {
		t.Fatalf("overflow size = %d/%t", overflowSize, ok)
	}
	// The invalid evidence version proves exact size rejection happens before
	// entry validation, singular-receipt allocation, or digest derivation.
	overflow.Receipts[0].EvidenceVersion = strings.Repeat("x", len(overflow.Receipts[0].EvidenceVersion))
	assertReceiptSetErrorContains(t, overflow, overflowRequired, "canonical bytes exceed")

	countOverflow := set
	countOverflow.Receipts = make([]ReceiptEntry, MaxReceipts+1)
	assertReceiptSetErrorContains(t, countOverflow, required, "exceeds 100000 entries")
}

type fieldExpectation struct {
	name   string
	typeOf reflect.Type
}

func assertExactFields(t *testing.T, valueType reflect.Type, expected []fieldExpectation) {
	t.Helper()
	if valueType.NumField() != len(expected) {
		t.Fatalf("%s has %d fields, want %d", valueType, valueType.NumField(), len(expected))
	}
	for index, want := range expected {
		field := valueType.Field(index)
		if field.Name != want.name || field.Type != want.typeOf {
			t.Fatalf("%s field[%d] = %s %s, want %s %s", valueType, index, field.Name, field.Type, want.name, want.typeOf)
		}
	}
}

func validReceipt(kind layoutbundlekeyv1.SlotOwnerKind) Receipt {
	key := receiptTestKey(kind)
	return Receipt{
		ReceiptVersion:              ReceiptVersion,
		OrgID:                       "org-layout",
		WriterCommandID:             receiptTestWriterCommandID,
		WriterReservationGeneration: 128,
		SourceRequestDigest:         receiptTestDigest('a'),
		RequiredBundleKeySetDigest:  receiptTestDigest('b'),
		BundleKey:                   key,
		EvidenceVersion:             receiptTestEvidenceVersion(kind),
		EvidenceDigest:              receiptTestDigest(ownerDigit(kind)),
		VerificationState:           VerificationStateVerified,
	}
}

func validReceiptSet(t *testing.T) (ReceiptSet, layoutbundlekeyv1.RequiredBundleKeySet) {
	t.Helper()
	app := receiptTestKey(layoutbundlekeyv1.SlotOwnerKindApp)
	tenant := receiptTestKey(layoutbundlekeyv1.SlotOwnerKindTenant)
	system := receiptTestKey(layoutbundlekeyv1.SlotOwnerKindSystem)
	required := layoutbundlekeyv1.RequiredBundleKeySet{
		Version:    layoutbundlekeyv1.RequiredBundleKeySetVersion,
		BundleKeys: []layoutbundlekeyv1.BundleKey{tenant, system, app},
	}
	requiredDigest, err := layoutbundlekeyv1.RequiredBundleKeySetDigest(required)
	if err != nil {
		t.Fatal(err)
	}
	return ReceiptSet{
		ReceiptSetVersion:           ReceiptSetVersion,
		ReceiptVersion:              ReceiptVersion,
		OrgID:                       "org-layout",
		WriterCommandID:             receiptTestWriterCommandID,
		WriterReservationGeneration: 128,
		SourceRequestDigest:         receiptTestDigest('a'),
		RequiredBundleKeySetDigest:  requiredDigest,
		Receipts: []ReceiptEntry{
			receiptEntry(system),
			receiptEntry(tenant),
			receiptEntry(app),
		},
	}, required
}

func receiptEntry(key layoutbundlekeyv1.BundleKey) ReceiptEntry {
	return ReceiptEntry{
		BundleKey:         key,
		EvidenceVersion:   receiptTestEvidenceVersion(key.SlotOwnerKind),
		EvidenceDigest:    receiptTestDigest(ownerDigit(key.SlotOwnerKind)),
		VerificationState: VerificationStateVerified,
	}
}

func receiptTestKey(kind layoutbundlekeyv1.SlotOwnerKind) layoutbundlekeyv1.BundleKey {
	namespace := ""
	switch kind {
	case layoutbundlekeyv1.SlotOwnerKindApp:
		namespace = "io.example.app"
	case layoutbundlekeyv1.SlotOwnerKindTenant:
		namespace = "io.example.tenant"
	case layoutbundlekeyv1.SlotOwnerKindSystem:
		namespace = layoutbundlekeyv1.SystemSlotOwnerNamespace
	}
	return layoutbundlekeyv1.BundleKey{
		SlotOwnerKind:      kind,
		SlotOwnerNamespace: namespace,
		LocalComponentKey:  receiptTestLocalKey(ownerDigit(kind)),
	}
}

func receiptTestEvidenceVersion(kind layoutbundlekeyv1.SlotOwnerKind) string {
	switch kind {
	case layoutbundlekeyv1.SlotOwnerKindApp:
		return AppAuthorityEvidenceVersion
	case layoutbundlekeyv1.SlotOwnerKindTenant:
		return TenantAuthorityEvidenceVersion
	case layoutbundlekeyv1.SlotOwnerKindSystem:
		return SystemAuthorityEvidenceVersion
	default:
		return ""
	}
}

func evidenceVersionForDifferentOwner(kind layoutbundlekeyv1.SlotOwnerKind) string {
	if kind == layoutbundlekeyv1.SlotOwnerKindApp {
		return TenantAuthorityEvidenceVersion
	}
	return AppAuthorityEvidenceVersion
}

func ownerDigit(kind layoutbundlekeyv1.SlotOwnerKind) byte {
	switch kind {
	case layoutbundlekeyv1.SlotOwnerKindApp:
		return '1'
	case layoutbundlekeyv1.SlotOwnerKindTenant:
		return '2'
	case layoutbundlekeyv1.SlotOwnerKindSystem:
		return '3'
	default:
		return '0'
	}
}

func receiptTestLocalKey(character byte) layoutbundlekeyv1.LocalComponentKey {
	return layoutbundlekeyv1.LocalComponentKey("key256:" + strings.Repeat(string(character), 64))
}

func receiptTestDigest(character byte) string {
	return "sha256:" + strings.Repeat(string(character), 64)
}

func assertReceiptErrorContains(t *testing.T, receipt Receipt, want string) {
	t.Helper()
	err := ValidateReceipt(receipt)
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Fatalf("ValidateReceipt error = %v, want substring %q", err, want)
	}
}

func assertReceiptSetErrorContains(
	t *testing.T,
	set ReceiptSet,
	required layoutbundlekeyv1.RequiredBundleKeySet,
	want string,
) {
	t.Helper()
	err := ValidateReceiptSet(set, required)
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Fatalf("ValidateReceiptSet error = %v, want substring %q", err, want)
	}
}

func receiptGenerationEncoding(t *testing.T, canonical []byte) []byte {
	t.Helper()
	offset := 0
	for range 3 {
		valueLength, prefixLength := readCanonicalUvarint(t, canonical[offset:])
		offset += prefixLength + int(valueLength)
	}
	_, length := readCanonicalUvarint(t, canonical[offset:])
	return append([]byte(nil), canonical[offset:offset+length]...)
}

func receiptCountEncoding(t *testing.T, canonical []byte) []byte {
	t.Helper()
	offset := 0
	for range 4 {
		valueLength, prefixLength := readCanonicalUvarint(t, canonical[offset:])
		offset += prefixLength + int(valueLength)
	}
	_, generationLength := readCanonicalUvarint(t, canonical[offset:])
	offset += generationLength
	for range 3 {
		valueLength, prefixLength := readCanonicalUvarint(t, canonical[offset:])
		offset += prefixLength + int(valueLength)
	}
	_, length := readCanonicalUvarint(t, canonical[offset:])
	return append([]byte(nil), canonical[offset:offset+length]...)
}

func readCanonicalUvarint(t *testing.T, canonical []byte) (uint64, int) {
	t.Helper()
	value, length := binary.Uvarint(canonical)
	if length <= 0 {
		t.Fatalf("invalid unsigned LEB128 at %x", canonical)
	}
	var encoded [binary.MaxVarintLen64]byte
	wantLength := binary.PutUvarint(encoded[:], value)
	if length != wantLength || !bytes.Equal(canonical[:length], encoded[:wantLength]) {
		t.Fatalf("non-minimal unsigned LEB128 %x", canonical[:length])
	}
	return value, length
}

func receiptCountSet(t *testing.T, count int) (ReceiptSet, layoutbundlekeyv1.RequiredBundleKeySet) {
	t.Helper()
	keys := make([]layoutbundlekeyv1.BundleKey, count)
	entries := make([]ReceiptEntry, count)
	for index := range count {
		key := layoutbundlekeyv1.BundleKey{
			SlotOwnerKind:      layoutbundlekeyv1.SlotOwnerKindTenant,
			SlotOwnerNamespace: "io.example.tenant",
			LocalComponentKey:  receiptTestLocalKeyFromIndex(index),
		}
		keys[count-index-1] = key
		entries[index] = receiptEntry(key)
	}
	required := layoutbundlekeyv1.RequiredBundleKeySet{
		Version:    layoutbundlekeyv1.RequiredBundleKeySetVersion,
		BundleKeys: keys,
	}
	requiredDigest, err := layoutbundlekeyv1.RequiredBundleKeySetDigest(required)
	if err != nil {
		t.Fatal(err)
	}
	return ReceiptSet{
		ReceiptSetVersion:           ReceiptSetVersion,
		ReceiptVersion:              ReceiptVersion,
		OrgID:                       "org-layout",
		WriterCommandID:             receiptTestWriterCommandID,
		WriterReservationGeneration: 128,
		SourceRequestDigest:         receiptTestDigest('a'),
		RequiredBundleKeySetDigest:  requiredDigest,
		Receipts:                    entries,
	}, required
}

func receiptTestLocalKeyFromIndex(index int) layoutbundlekeyv1.LocalComponentKey {
	return layoutbundlekeyv1.LocalComponentKey(fmt.Sprintf("key256:%064x", index))
}

func exactSizeBoundaryReceiptSet(t *testing.T) (ReceiptSet, layoutbundlekeyv1.RequiredBundleKeySet) {
	t.Helper()
	keys := make([]layoutbundlekeyv1.BundleKey, MaxReceipts)
	entries := make([]ReceiptEntry, MaxReceipts)
	for offset := range MaxReceipts {
		index := MaxReceipts - offset - 1
		namespaceBytes := 126
		if index >= 94_735 {
			namespaceBytes = 127
		}
		key := layoutbundlekeyv1.BundleKey{
			SlotOwnerKind:      layoutbundlekeyv1.SlotOwnerKindTenant,
			SlotOwnerNamespace: receiptBoundaryNamespace(index, namespaceBytes),
			LocalComponentKey:  receiptTestLocalKey('1'),
		}
		keys[offset] = key
		entries[offset] = ReceiptEntry{
			BundleKey:         key,
			EvidenceVersion:   TenantAuthorityEvidenceVersion,
			EvidenceDigest:    receiptTestDigest('2'),
			VerificationState: VerificationStateVerified,
		}
	}
	required := layoutbundlekeyv1.RequiredBundleKeySet{
		Version:    layoutbundlekeyv1.RequiredBundleKeySetVersion,
		BundleKeys: keys,
	}
	requiredDigest, err := layoutbundlekeyv1.RequiredBundleKeySetDigest(required)
	if err != nil {
		t.Fatal(err)
	}
	return ReceiptSet{
		ReceiptSetVersion:           ReceiptSetVersion,
		ReceiptVersion:              ReceiptVersion,
		OrgID:                       strings.Repeat("o", 255),
		WriterCommandID:             "ffffffff-ffff-7fff-bfff-ffffffffffff",
		WriterReservationGeneration: math.MaxUint64,
		SourceRequestDigest:         receiptTestDigest('a'),
		RequiredBundleKeySetDigest:  requiredDigest,
		Receipts:                    entries,
	}, required
}

func receiptBoundaryNamespace(index, size int) string {
	firstSegment := strings.Repeat("a", 57) + fmt.Sprintf("%06x", index)
	secondSegment := strings.Repeat("b", size-len(firstSegment)-1)
	return firstSegment + "." + secondSegment
}
