package packs

import (
	"context"
	"strings"
	"testing"

	"github.com/nexuscrm/kernel/pkg/formula"
)

type runtimeStartupShallowPersistedCompatPack struct{}

func (runtimeStartupShallowPersistedCompatPack) Name() string { return "compat-pack" }

func (runtimeStartupShallowPersistedCompatPack) Category() Category { return AppPack }

func (runtimeStartupShallowPersistedCompatPack) Apply(context.Context, ApplyDeps) error { return nil }

func (runtimeStartupShallowPersistedCompatPack) Verify(context.Context, VerifyDeps) error { return nil }

func (runtimeStartupShallowPersistedCompatPack) RuntimeStartupShallowDeclaredRows() []runtimeStartupShallowDeclaredRow {
	permissionProjection, _ := marshalRuntimeStartupShallowProjection(runtimeStartupShallowPermissionProjection{
		APIName:   "ViewSetup",
		Label:     "View Setup",
		Category:  "Administrative",
		OwnerPack: "compat-pack",
		IsSystem:  true,
		IsActive:  true,
	})
	validationRuleProjection, _ := marshalRuntimeStartupShallowProjection(runtimeStartupShallowValidationRuleProjection{
		ObjectAPIName: "Lead",
		Name:          "RequireName",
		Active:        true,
		Condition:     "ISBLANK(Name)",
		ErrorMessage:  "Name is required",
		OwnerPack:     "compat-pack",
	})
	listFieldsProjection, _ := marshalRuntimeStartupShallowProjection(runtimeStartupShallowListFieldsProjection{
		ObjectAPIName: "Lead",
		Fields:        []string{"Name", "Company"},
	})
	return []runtimeStartupShallowDeclaredRow{
		{Kind: ComponentKindListFields, BusinessKey: "Lead", Projection: listFieldsProjection},
		{Kind: ComponentKindPermission, BusinessKey: "ViewSetup", Projection: permissionProjection},
		{Kind: ComponentKindValidationRule, BusinessKey: "Lead/RequireName", Projection: validationRuleProjection},
	}
}

type runtimeStartupShallowEmptyListFieldsPersistedCompatPack struct{}

func (runtimeStartupShallowEmptyListFieldsPersistedCompatPack) Name() string {
	return "empty-list-fields-pack"
}

func (runtimeStartupShallowEmptyListFieldsPersistedCompatPack) Category() Category { return AppPack }

func (runtimeStartupShallowEmptyListFieldsPersistedCompatPack) Apply(context.Context, ApplyDeps) error {
	return nil
}

func (runtimeStartupShallowEmptyListFieldsPersistedCompatPack) Verify(context.Context, VerifyDeps) error {
	return nil
}

func (runtimeStartupShallowEmptyListFieldsPersistedCompatPack) RuntimeStartupShallowDeclaredRows() []runtimeStartupShallowDeclaredRow {
	listFieldsProjection, _ := marshalRuntimeStartupShallowProjection(runtimeStartupShallowListFieldsProjection{
		ObjectAPIName: "Lead",
		Fields:        []string{},
	})
	return []runtimeStartupShallowDeclaredRow{
		{Kind: ComponentKindListFields, BusinessKey: "Lead", Projection: listFieldsProjection},
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackRejectsProjectionlessListFieldsStartupShallow(t *testing.T) {
	pack := runtimeStartupShallowPersistedCompatPack{}
	rows := pack.RuntimeStartupShallowDeclaredRows()
	for i := range rows {
		if rows[i].Kind == ComponentKindListFields {
			rows[i].Projection = ""
		}
	}
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(rows)
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	err = VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), `[]`, `[]`, `[]`, startupShallowJSON, pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want drift error", err)
	}
}

func TestPersistedRuntimeDeclarationRoundTripsFormulaFunctionBundles(t *testing.T) {
	if err := formula.RegisterRuntimeFunctionBundles(nil); err != nil {
		t.Fatalf("clear runtime formula bundles before test: %v", err)
	}
	t.Cleanup(func() {
		_ = formula.RegisterRuntimeFunctionBundles(nil)
	})

	pack := testPersistedRuntimeSourceBackedPack(t, []ManifestComponent{{
		Kind:          ComponentKindFormulaFunctionBundle,
		BusinessKey:   "probe-functions",
		Manageability: ManageabilityLocked,
		Payload:       []byte(testFormulaFunctionBundleComponentPayload()),
	}})
	expected, err := BuildPersistedRuntimeDeclaration(pack)
	if err != nil {
		t.Fatalf("BuildPersistedRuntimeDeclaration: %v", err)
	}
	if got := expected.FormulaFunctionBundlesJSON(); !strings.Contains(got, "PACK_PREFIX") {
		t.Fatalf("FormulaFunctionBundlesJSON = %q, want PACK_PREFIX payload", got)
	}

	loaded, err := LoadPersistedRuntimePackWithSearchAllDefaultFieldsAndFormulaFunctionBundles(
		pack.Name(),
		expected.ObjectPayloadsJSON(),
		expected.RelatedListRulesJSON(),
		expected.SearchScopeOrderJSON(),
		expected.SearchAllDefaultFieldsJSON(),
		expected.FormulaFunctionBundlesJSON(),
	)
	if err != nil {
		t.Fatalf("LoadPersistedRuntimePackWithSearchAllDefaultFieldsAndFormulaFunctionBundles: %v", err)
	}
	if err := RegisterRuntimeMetadataForPacks(context.Background(), nil, []Pack{loaded}); err != nil {
		t.Fatalf("RegisterRuntimeMetadataForPacks with persisted formula bundle: %v", err)
	}

	engine := formula.NewEngine()
	got, err := engine.Evaluate(`PACK_PREFIX(Name)`, &formula.Context{Record: map[string]interface{}{"Name": "alpha"}})
	if err != nil {
		t.Fatalf("Evaluate PACK_PREFIX from persisted runtime bundle: %v", err)
	}
	if got != "alpha-probe" {
		t.Fatalf("Evaluate PACK_PREFIX from persisted runtime bundle = %v, want alpha-probe", got)
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackAcceptsLegacyProjectionlessNonListFieldsStartupShallow(t *testing.T) {
	pack := runtimeStartupShallowPersistedCompatPack{}
	rows := pack.RuntimeStartupShallowDeclaredRows()
	for i := range rows {
		switch rows[i].Kind {
		case ComponentKindPermission, ComponentKindValidationRule:
			rows[i].Projection = ""
		}
	}
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(rows)
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	if err := VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), `[]`, `[]`, `[]`, startupShallowJSON, pack); err != nil {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack: %v", err)
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackAcceptsRetiredApprovalProcessStartupShallowRow(t *testing.T) {
	pack := runtimeStartupShallowPersistedCompatPack{}
	rows := append(pack.RuntimeStartupShallowDeclaredRows(), runtimeStartupShallowDeclaredRow{
		Kind:        ComponentKindApprovalProcess,
		BusinessKey: "Lead/LeadApproval",
		Projection:  `{"objectApiName":"Lead","developerName":"LeadApproval","ownerPack":"compat-pack"}`,
	})
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(rows)
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	if err := VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), `[]`, `[]`, `[]`, startupShallowJSON, pack); err != nil {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack: %v", err)
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackAcceptsLegacyEmptyListFieldsProjection(t *testing.T) {
	pack := runtimeStartupShallowEmptyListFieldsPersistedCompatPack{}
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows([]runtimeStartupShallowDeclaredRow{
		{
			Kind:        ComponentKindListFields,
			BusinessKey: "Lead",
			Projection:  `{"objectApiName":"Lead","fields":null}`,
		},
	})
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	if err := VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), `[]`, `[]`, `[]`, startupShallowJSON, pack); err != nil {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack: %v", err)
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackRejectsListFieldsProjectionDrift(t *testing.T) {
	pack := runtimeStartupShallowEmptyListFieldsPersistedCompatPack{}
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows([]runtimeStartupShallowDeclaredRow{
		{
			Kind:        ComponentKindListFields,
			BusinessKey: "Lead",
			Projection:  `{"objectApiName":"Lead","fields":["Name"]}`,
		},
	})
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	err = VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), `[]`, `[]`, `[]`, startupShallowJSON, pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want drift error", err)
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackAcceptsLegacyMissingRecordTypeStartupShallowRows(t *testing.T) {
	pack := testPersistedRuntimeSourceBackedPack(t, []ManifestComponent{{
		Kind:          ComponentKindRecordType,
		BusinessKey:   "record-types",
		Manageability: ManageabilityLocked,
		Payload:       []byte(`{"recordTypes":[{"objectApiName":"Account","types":[{"name":"Contract Only (APAC)"}]}]}`),
	}})
	expected, err := BuildPersistedRuntimeDeclaration(pack)
	if err != nil {
		t.Fatalf("BuildPersistedRuntimeDeclaration: %v", err)
	}
	legacyRows := persistedRuntimeStartupShallowRowsWithoutKind(t, expected.StartupShallowDeclaredRowsJSON(), ComponentKindRecordType)
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(legacyRows)
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	if err := VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), expected.ObjectPayloadsJSON(), expected.RelatedListRulesJSON(), expected.SearchScopeOrderJSON(), startupShallowJSON, pack); err != nil {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack: %v", err)
	}
}

func TestPersistedRuntimeDeclarationDetectsLegacyListFieldsAndRecordTypeStartupShallowOmission(t *testing.T) {
	pack := testPersistedRuntimeSourceBackedPack(t, []ManifestComponent{
		{
			Kind:          ComponentKindObjectSpec,
			BusinessKey:   "object:Lead",
			Manageability: ManageabilityLocked,
			Payload:       []byte(testObjectSpecPayloadWithListFields("Lead", []string{"Name", "Company"})),
		},
		{
			Kind:          ComponentKindRecordType,
			BusinessKey:   "record-types",
			Manageability: ManageabilityLocked,
			Payload:       []byte(`{"recordTypes":[{"objectApiName":"Lead","types":[{"name":"Contract Only"}]}]}`),
		},
	})
	expected, err := BuildPersistedRuntimeDeclaration(pack)
	if err != nil {
		t.Fatalf("BuildPersistedRuntimeDeclaration: %v", err)
	}
	rows, err := unmarshalRuntimeStartupShallowDeclaredRows(expected.StartupShallowDeclaredRowsJSON())
	if err != nil {
		t.Fatalf("unmarshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	legacyRows := rows[:0:0]
	for _, row := range rows {
		if row.Kind == ComponentKindListFields || row.Kind == ComponentKindRecordType {
			continue
		}
		legacyRows = append(legacyRows, row)
	}
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(legacyRows)
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	err = VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), expected.ObjectPayloadsJSON(), expected.RelatedListRulesJSON(), expected.SearchScopeOrderJSON(), startupShallowJSON, pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want strict drift error", err)
	}
	if !PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmission(pack.Name(), expected.ObjectPayloadsJSON(), expected.RelatedListRulesJSON(), expected.SearchScopeOrderJSON(), startupShallowJSON, pack) {
		t.Fatal("PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmission = false, want true")
	}
}

func TestPersistedRuntimeDeclarationLegacyListFieldsOmissionDoesNotMatchMissingRecordTypeRows(t *testing.T) {
	pack := testPersistedRuntimeSourceBackedPack(t, []ManifestComponent{{
		Kind:          ComponentKindRecordType,
		BusinessKey:   "record-types",
		Manageability: ManageabilityLocked,
		Payload:       []byte(`{"recordTypes":[{"objectApiName":"Account","types":[{"name":"Contract Only (APAC)"}]}]}`),
	}})
	expected, err := BuildPersistedRuntimeDeclaration(pack)
	if err != nil {
		t.Fatalf("BuildPersistedRuntimeDeclaration: %v", err)
	}
	legacyRows := persistedRuntimeStartupShallowRowsWithoutKind(t, expected.StartupShallowDeclaredRowsJSON(), ComponentKindRecordType)
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(legacyRows)
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	if PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmission(pack.Name(), expected.ObjectPayloadsJSON(), expected.RelatedListRulesJSON(), expected.SearchScopeOrderJSON(), startupShallowJSON, pack) {
		t.Fatal("legacy list_fields omission matcher accepted missing record_type rows")
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackRejectsRecordTypeBlankProjection(t *testing.T) {
	pack := testPersistedRuntimeSourceBackedPack(t, []ManifestComponent{{
		Kind:          ComponentKindRecordType,
		BusinessKey:   "record-types",
		Manageability: ManageabilityLocked,
		Payload:       []byte(`{"recordTypes":[{"objectApiName":"Account","types":[{"name":"Contract Only (APAC)"}]}]}`),
	}})
	expected, err := BuildPersistedRuntimeDeclaration(pack)
	if err != nil {
		t.Fatalf("BuildPersistedRuntimeDeclaration: %v", err)
	}
	rows, err := unmarshalRuntimeStartupShallowDeclaredRows(expected.StartupShallowDeclaredRowsJSON())
	if err != nil {
		t.Fatalf("unmarshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	for i := range rows {
		if rows[i].Kind == ComponentKindRecordType {
			rows[i].Projection = ""
		}
	}
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(rows)
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	err = VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), expected.ObjectPayloadsJSON(), expected.RelatedListRulesJSON(), expected.SearchScopeOrderJSON(), startupShallowJSON, pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want record_type blank projection drift", err)
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackRejectsRecordTypeProjectionDrift(t *testing.T) {
	pack := testPersistedRuntimeSourceBackedPack(t, []ManifestComponent{{
		Kind:          ComponentKindRecordType,
		BusinessKey:   "record-types",
		Manageability: ManageabilityLocked,
		Payload:       []byte(`{"recordTypes":[{"objectApiName":"Account","types":[{"name":"Contract Only (APAC)"}]}]}`),
	}})
	expected, err := BuildPersistedRuntimeDeclaration(pack)
	if err != nil {
		t.Fatalf("BuildPersistedRuntimeDeclaration: %v", err)
	}
	rows, err := unmarshalRuntimeStartupShallowDeclaredRows(expected.StartupShallowDeclaredRowsJSON())
	if err != nil {
		t.Fatalf("unmarshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	for i := range rows {
		if rows[i].Kind == ComponentKindRecordType {
			rows[i].Projection = `{"objectApiName":"Account","name":"Contract Only (EMEA)","developerName":"Contract_Only_APAC","sobjectType":"Account","isActive":true,"isMaster":false,"ownerPack":"persisted-runtime-source-pack"}`
		}
	}
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(rows)
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	err = VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), expected.ObjectPayloadsJSON(), expected.RelatedListRulesJSON(), expected.SearchScopeOrderJSON(), startupShallowJSON, pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want record_type projection drift", err)
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackRejectsOrphanRecordTypeStartupShallowRow(t *testing.T) {
	pack := testPersistedRuntimeSourceBackedPack(t, nil)
	expected, err := BuildPersistedRuntimeDeclaration(pack)
	if err != nil {
		t.Fatalf("BuildPersistedRuntimeDeclaration: %v", err)
	}
	projection, err := marshalRuntimeStartupShallowProjection(sourceBackedRecordTypeRow{
		ObjectAPIName: "Account",
		Name:          "Contract Only (APAC)",
		DeveloperName: "Contract_Only_APAC",
		SobjectType:   "Account",
		IsActive:      true,
		IsMaster:      false,
		OwnerPack:     pack.Name(),
	})
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowProjection: %v", err)
	}
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows([]runtimeStartupShallowDeclaredRow{{
		Kind:        ComponentKindRecordType,
		BusinessKey: JoinComponentBusinessKey("Account", "Contract_Only_APAC"),
		Projection:  projection,
	}})
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	err = VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), expected.ObjectPayloadsJSON(), expected.RelatedListRulesJSON(), expected.SearchScopeOrderJSON(), startupShallowJSON, pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want orphan record_type drift", err)
	}
}

func persistedRuntimeStartupShallowRowsWithoutKind(t *testing.T, rowsJSON string, kind ComponentKind) []runtimeStartupShallowDeclaredRow {
	t.Helper()
	rows, err := unmarshalRuntimeStartupShallowDeclaredRows(rowsJSON)
	if err != nil {
		t.Fatalf("unmarshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	out := rows[:0:0]
	for _, row := range rows {
		if row.Kind == kind {
			continue
		}
		out = append(out, row)
	}
	return out
}

func TestPersistedRuntimeDeclarationDetectsLegacyObjectSpecListFieldsStartupShallowOmission(t *testing.T) {
	pack := testPersistedRuntimeSourceBackedPack(t, []ManifestComponent{{
		Kind:          ComponentKindObjectSpec,
		BusinessKey:   "object:Lead",
		Manageability: ManageabilityLocked,
		Payload:       []byte(testObjectSpecPayloadWithListFields("Lead", []string{"Name", "Company"})),
	}})
	expected, err := BuildPersistedRuntimeDeclaration(pack)
	if err != nil {
		t.Fatalf("BuildPersistedRuntimeDeclaration: %v", err)
	}
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(nil)
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	err = VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), expected.ObjectPayloadsJSON(), expected.RelatedListRulesJSON(), expected.SearchScopeOrderJSON(), startupShallowJSON, pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want strict drift error", err)
	}
	if !PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmission(pack.Name(), expected.ObjectPayloadsJSON(), expected.RelatedListRulesJSON(), expected.SearchScopeOrderJSON(), startupShallowJSON, pack) {
		t.Fatal("PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmission = false, want true")
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackRejectsLegacyStandaloneListFieldsStartupShallowOmission(t *testing.T) {
	pack := testPersistedRuntimeSourceBackedPack(t, []ManifestComponent{
		{
			Kind:          ComponentKindObjectSpec,
			BusinessKey:   "object:Lead",
			Manageability: ManageabilityLocked,
			Payload:       []byte(testObjectSpecPayload("Lead")),
		},
		{
			Kind:          ComponentKindListFields,
			BusinessKey:   "lead-list-fields",
			Manageability: ManageabilityLocked,
			Payload:       []byte(`{"Lead":["Name","Company"]}`),
		},
	})
	expected, err := BuildPersistedRuntimeDeclaration(pack)
	if err != nil {
		t.Fatalf("BuildPersistedRuntimeDeclaration: %v", err)
	}
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(nil)
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	err = VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), expected.ObjectPayloadsJSON(), expected.RelatedListRulesJSON(), expected.SearchScopeOrderJSON(), startupShallowJSON, pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want drift error", err)
	}
	if PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmission(pack.Name(), expected.ObjectPayloadsJSON(), expected.RelatedListRulesJSON(), expected.SearchScopeOrderJSON(), startupShallowJSON, pack) {
		t.Fatal("PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmission = true, want false for standalone list_fields")
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackRejectsLegacyObjectSpecListFieldsOmissionWhenStandaloneOverrides(t *testing.T) {
	pack := testPersistedRuntimeSourceBackedPack(t, []ManifestComponent{
		{
			Kind:          ComponentKindObjectSpec,
			BusinessKey:   "object:Lead",
			Manageability: ManageabilityDefaultsOnly,
			Payload:       []byte(testObjectSpecPayloadWithListFields("Lead", []string{"Name"})),
		},
		{
			Kind:          ComponentKindListFields,
			BusinessKey:   "lead-list-fields",
			Manageability: ManageabilityLocked,
			Payload:       []byte(`{"Lead":["Name","Company"]}`),
		},
	})
	expected, err := BuildPersistedRuntimeDeclaration(pack)
	if err != nil {
		t.Fatalf("BuildPersistedRuntimeDeclaration: %v", err)
	}
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(nil)
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	err = VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), expected.ObjectPayloadsJSON(), expected.RelatedListRulesJSON(), expected.SearchScopeOrderJSON(), startupShallowJSON, pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want drift error", err)
	}
	if PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmission(pack.Name(), expected.ObjectPayloadsJSON(), expected.RelatedListRulesJSON(), expected.SearchScopeOrderJSON(), startupShallowJSON, pack) {
		t.Fatal("PersistedRuntimeDeclarationMatchesLegacyObjectSpecListFieldsStartupShallowOmission = true, want false when standalone overrides")
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackRejectsNonLegacyEquivalentListFieldsProjection(t *testing.T) {
	pack := runtimeStartupShallowEmptyListFieldsPersistedCompatPack{}
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows([]runtimeStartupShallowDeclaredRow{
		{
			Kind:        ComponentKindListFields,
			BusinessKey: "Lead",
			Projection:  `{"fields":[],"objectApiName":"Lead"}`,
		},
	})
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	err = VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), `[]`, `[]`, `[]`, startupShallowJSON, pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want drift error", err)
	}
}

func testPersistedRuntimeSourceBackedPack(t *testing.T, components []ManifestComponent) *SourceBackedPack {
	t.Helper()
	pack, err := NewSourceBackedPack(&ResolvedPackSource{
		Kind: PackSourceKindLocalPath,
		URI:  "/tmp/source-pack",
		Manifest: &PackManifest{
			ManifestFormatVersion: SupportedManifestFormatVersion,
			Name:                  "persisted-runtime-source-pack",
			DisplayName:           "Persisted Runtime Source Pack",
			Category:              AppPack,
			Version:               "0.1.0",
			PlatformCompatibility: PlatformCompatibility{Min: "0.1.0", MaxExclusive: "0.2.0"},
			Components:            components,
		},
	})
	if err != nil {
		t.Fatalf("NewSourceBackedPack: %v", err)
	}
	return pack
}

func TestPersistedRuntimeDeclarationJSONLoadPackRequiresStrictCompleteArrays(t *testing.T) {
	valid := PersistedRuntimeDeclarationJSON{
		ObjectSpecs: "[]", RelatedLists: "[]", SearchScope: "[]",
		SearchAllDefaultFields: "[]", FormulaFunctionBundles: "[]",
		StartupShallow: `[{"kind":"permission","businessKey":"LegacyPermission"}]`,
	}
	loaded, err := valid.LoadPack("strict-runtime-pack")
	if err != nil {
		t.Fatalf("load valid complete runtime declaration: %v", err)
	}
	provider, ok := loaded.(runtimeStartupShallowDeclarationProvider)
	if !ok {
		t.Fatal("loaded persisted runtime pack does not retain startup-shallow declarations")
	}
	rows := provider.RuntimeStartupShallowDeclaredRows()
	if len(rows) != 1 || rows[0].Kind != ComponentKindPermission || rows[0].BusinessKey != "LegacyPermission" {
		t.Fatalf("loaded persisted startup-shallow declarations = %#v, want exact permission row", rows)
	}
	registrationRows := buildRuntimeDeclaration(loaded).startupShallowRows
	if len(registrationRows) != 1 || registrationRows[0] != rows[0] {
		t.Fatalf("registered persisted startup-shallow declarations = %#v, want %#v", registrationRows, rows)
	}

	malformed := valid
	malformed.StartupShallow = `[{"kind":"connector_callout_profile"}]`
	if _, err := malformed.LoadPack("strict-runtime-pack"); err == nil || !strings.Contains(err.Error(), "missing kind or business key") {
		t.Fatalf("partial startup-shallow declaration error = %v, want strict missing business key", err)
	}
	malformed = valid
	malformed.RelatedLists = `[null]`
	if _, err := malformed.LoadPack("strict-runtime-pack"); err == nil || !strings.Contains(err.Error(), "row 0 is malformed") {
		t.Fatalf("null related-list declaration error = %v, want strict malformed row", err)
	}
	malformed = valid
	malformed.StartupShallow = `[{"kind":"record_type","businessKey":"Account/Business","projection":"{"}]`
	if _, err := malformed.LoadPack("strict-runtime-pack"); err == nil || !strings.Contains(err.Error(), "unexpected end of JSON input") {
		t.Fatalf("malformed record-type projection error = %v, want strict projection parse failure", err)
	}
}

func TestPersistedRuntimeDeclarationJSONLoadPackWithLegacyConnectorCalloutProjectionSource(t *testing.T) {
	sourcePack, err := NewSourceBackedPack(&ResolvedPackSource{
		Kind: PackSourceKindOfficialRepo,
		URI:  "legacy-connector",
		Manifest: &PackManifest{
			ManifestFormatVersion: SupportedManifestFormatVersion,
			Name:                  "legacy-connector",
			DisplayName:           "Legacy Connector",
			Category:              ConnectorPack,
			Version:               "0.1.0",
			PlatformCompatibility: PlatformCompatibility{Min: "0.1.0", MaxExclusive: "0.2.0"},
			Components: []ManifestComponent{{
				Kind:          ComponentKindConnectorCalloutProfile,
				BusinessKey:   "legacy-connector/default",
				Manageability: ManageabilityLocked,
				Payload:       []byte(`{"profileName":"default","credentialRef":"credential-a","endpointClass":"crm.read","description":"Legacy connector fixture","retryPolicy":{"maxAttempts":3,"baseDelay":1000000,"multiplier":2,"maxDelay":10000000,"retryableStatusCodes":[429,503]}}`),
			}},
		},
	})
	if err != nil {
		t.Fatalf("construct legacy connector source: %v", err)
	}
	expected, err := BuildPersistedRuntimeDeclaration(sourcePack)
	if err != nil {
		t.Fatalf("build current connector declaration: %v", err)
	}
	legacy := PersistedRuntimeDeclarationJSON{
		ObjectSpecs: expected.ObjectPayloadsJSON(), RelatedLists: expected.RelatedListRulesJSON(),
		SearchScope: expected.SearchScopeOrderJSON(), SearchAllDefaultFields: expected.SearchAllDefaultFieldsJSON(),
		FormulaFunctionBundles: expected.FormulaFunctionBundlesJSON(),
		StartupShallow:         `[{"kind":"connector_callout_profile","businessKey":"default"}]`,
	}
	if _, err := legacy.LoadPack(sourcePack.Name()); err == nil || !strings.Contains(err.Error(), "projection is required") {
		t.Fatalf("strict legacy connector declaration error = %v, want projection requirement", err)
	}
	loaded, err := legacy.LoadPackWithLegacyConnectorCalloutProfileProjectionSource(sourcePack.Name(), sourcePack)
	if err != nil {
		t.Fatalf("load exact legacy connector declaration: %v", err)
	}
	bridged, err := BuildPersistedRuntimeDeclaration(loaded)
	if err != nil {
		t.Fatalf("build bridged connector declaration: %v", err)
	}
	if bridged.StartupShallowDeclaredRowsJSON() != expected.StartupShallowDeclaredRowsJSON() {
		t.Fatalf("bridged startup shallow = %s, want %s", bridged.StartupShallowDeclaredRowsJSON(), expected.StartupShallowDeclaredRowsJSON())
	}

	wrongSource, err := NewSourceBackedPack(&ResolvedPackSource{
		Kind: PackSourceKindOfficialRepo, URI: "legacy-connector",
		Manifest: &PackManifest{
			ManifestFormatVersion: SupportedManifestFormatVersion,
			Name:                  "legacy-connector", DisplayName: "Legacy Connector", Category: ConnectorPack, Version: "0.1.0",
			PlatformCompatibility: PlatformCompatibility{Min: "0.1.0", MaxExclusive: "0.2.0"},
		},
	})
	if err != nil {
		t.Fatalf("construct missing-row source: %v", err)
	}
	if _, err := legacy.LoadPackWithLegacyConnectorCalloutProfileProjectionSource(sourcePack.Name(), wrongSource); err == nil || !strings.Contains(err.Error(), "missing exact source projection") {
		t.Fatalf("missing source projection error = %v, want exact-source rejection", err)
	}

	sourceWithExtraRow, err := NewSourceBackedPack(&ResolvedPackSource{
		Kind: PackSourceKindOfficialRepo, URI: "legacy-connector",
		Manifest: &PackManifest{
			ManifestFormatVersion: SupportedManifestFormatVersion,
			Name:                  "legacy-connector", DisplayName: "Legacy Connector", Category: ConnectorPack, Version: "0.1.0",
			PlatformCompatibility: PlatformCompatibility{Min: "0.1.0", MaxExclusive: "0.2.0"},
			Components: []ManifestComponent{
				{
					Kind:          ComponentKindConnectorCalloutProfile,
					BusinessKey:   "legacy-connector/default",
					Manageability: ManageabilityLocked,
					Payload:       []byte(`{"profileName":"default","credentialRef":"credential-a","endpointClass":"crm.read","description":"Legacy connector fixture","retryPolicy":{"maxAttempts":3,"baseDelay":1000000,"multiplier":2,"maxDelay":10000000,"retryableStatusCodes":[429,503]}}`),
				},
				{
					Kind:          ComponentKindConnectorCalloutProfile,
					BusinessKey:   "legacy-connector/secondary",
					Manageability: ManageabilityLocked,
					Payload:       []byte(`{"profileName":"secondary","credentialRef":"credential-b","endpointClass":"crm.write","description":"Secondary connector fixture","retryPolicy":{"maxAttempts":2,"baseDelay":1000000,"multiplier":2,"maxDelay":10000000,"retryableStatusCodes":[429,503]}}`),
				},
			},
		},
	})
	if err != nil {
		t.Fatalf("construct extra-row source: %v", err)
	}
	if _, err := legacy.LoadPackWithLegacyConnectorCalloutProfileProjectionSource(sourcePack.Name(), sourceWithExtraRow); err == nil || !strings.Contains(err.Error(), "missing exact persisted declaration") {
		t.Fatalf("missing persisted declaration error = %v, want exact key-set rejection", err)
	}

	drifted := legacy
	drifted.RelatedLists = `[{"parentObject":"Account","relatedObject":"Contact","relationshipName":"Contacts"}]`
	if _, err := drifted.LoadPackWithLegacyConnectorCalloutProfileProjectionSource(sourcePack.Name(), sourcePack); err == nil || !strings.Contains(err.Error(), "does not match the exact source declaration") {
		t.Fatalf("non-connector declaration drift error = %v, want exact-source declaration rejection", err)
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackRejectsMissingStartupShallowWhenExpectedRowsExist(t *testing.T) {
	pack := runtimeStartupShallowPersistedCompatPack{}
	err := VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), `[]`, `[]`, `[]`, "", pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want drift error", err)
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackRejectsMalformedStartupShallowWhenExpectedRowsEmpty(t *testing.T) {
	pack := &persistedRuntimePack{name: "empty-pack"}
	for _, startupShallowJSON := range []string{`not-json`, `{}`, `null`, `[{}]`, `[null]`} {
		t.Run(startupShallowJSON, func(t *testing.T) {
			err := VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), `[]`, `[]`, `[]`, startupShallowJSON, pack)
			if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
				t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want drift error", err)
			}
		})
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackAcceptsLegacyInactiveValidationRuleOmittedFromSource(t *testing.T) {
	pack := runtimeStartupShallowPersistedCompatPack{}
	inactiveProjection, err := marshalRuntimeStartupShallowProjection(runtimeStartupShallowValidationRuleProjection{
		ObjectAPIName: "Lead",
		Name:          "LegacyInactive",
		Active:        false,
		Condition:     "ISBLANK(Company)",
		ErrorMessage:  "Company is required",
		OwnerPack:     "compat-pack",
	})
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowProjection: %v", err)
	}
	rows := append(pack.RuntimeStartupShallowDeclaredRows(), runtimeStartupShallowDeclaredRow{
		Kind:        ComponentKindValidationRule,
		BusinessKey: JoinComponentBusinessKey("Lead", "LegacyInactive"),
		Projection:  inactiveProjection,
	})
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(rows)
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	if err := VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), `[]`, `[]`, `[]`, startupShallowJSON, pack); err != nil {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack: %v", err)
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackAcceptsProjectionlessLegacyInactiveValidationRuleOmittedFromSource(t *testing.T) {
	pack := runtimeStartupShallowSourceBackedValidationRuleCompatPack(t)
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(append(pack.RuntimeStartupShallowDeclaredRows(),
		runtimeStartupShallowDeclaredRow{Kind: ComponentKindValidationRule, BusinessKey: JoinComponentBusinessKey("Task", "RequireStatus")}))
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	if err := VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), `[]`, `[]`, `[]`, startupShallowJSON, pack); err != nil {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack: %v", err)
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackRejectsProjectionlessActiveValidationRuleOmittedFromSource(t *testing.T) {
	pack := runtimeStartupShallowSourceBackedValidationRuleCompatPack(t)
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(append(pack.RuntimeStartupShallowDeclaredRows(),
		runtimeStartupShallowDeclaredRow{Kind: ComponentKindValidationRule, BusinessKey: JoinComponentBusinessKey("Task", "UnexpectedActive")}))
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	err = VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), `[]`, `[]`, `[]`, startupShallowJSON, pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want drift error", err)
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackRejectsActiveValidationRuleOmittedFromSource(t *testing.T) {
	pack := runtimeStartupShallowPersistedCompatPack{}
	activeProjection, err := marshalRuntimeStartupShallowProjection(runtimeStartupShallowValidationRuleProjection{
		ObjectAPIName: "Lead",
		Name:          "UnexpectedActive",
		Active:        true,
		Condition:     "ISBLANK(Company)",
		ErrorMessage:  "Company is required",
		OwnerPack:     "compat-pack",
	})
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowProjection: %v", err)
	}
	rows := append(pack.RuntimeStartupShallowDeclaredRows(), runtimeStartupShallowDeclaredRow{
		Kind:        ComponentKindValidationRule,
		BusinessKey: JoinComponentBusinessKey("Lead", "UnexpectedActive"),
		Projection:  activeProjection,
	})
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(rows)
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	err = VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), `[]`, `[]`, `[]`, startupShallowJSON, pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want drift error", err)
	}
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackRejectsMalformedInactiveValidationRuleOmittedFromSource(t *testing.T) {
	pack := runtimeStartupShallowPersistedCompatPack{}
	rows := append(pack.RuntimeStartupShallowDeclaredRows(), runtimeStartupShallowDeclaredRow{
		Kind:        ComponentKindValidationRule,
		BusinessKey: JoinComponentBusinessKey("Lead", "LegacyInactive"),
		Projection:  `{"objectApiName":"Lead","name":"LegacyInactive","active":false,"ownerPack":"compat-pack"}`,
	})
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows(rows)
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	err = VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), `[]`, `[]`, `[]`, startupShallowJSON, pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want drift error", err)
	}
}

func runtimeStartupShallowSourceBackedValidationRuleCompatPack(t *testing.T) *SourceBackedPack {
	t.Helper()
	source := &ResolvedPackSource{
		Kind: PackSourceKindLocalPath,
		URI:  "/tmp/runtime-startup-shallow-compat",
		Manifest: &PackManifest{
			ManifestFormatVersion: SupportedManifestFormatVersion,
			Name:                  "compat-pack",
			DisplayName:           "Compat Pack",
			Category:              AppPack,
			Version:               "0.1.0",
			PlatformCompatibility: PlatformCompatibility{Min: "0.1.0", MaxExclusive: "0.2.0"},
			Components: []ManifestComponent{{
				Kind:          ComponentKindValidationRule,
				BusinessKey:   "task-rules",
				Manageability: ManageabilityDefaultsOnly,
				Payload: []byte(`{"validationRules":[
					{
						"id":"vr_active",
						"objectApiName":"Task",
						"name":"RequireSubject",
						"active":true,
						"condition":"ISBLANK(Subject)",
						"errorMessage":"Subject is required"
					},
					{
						"id":"vr_inactive",
						"objectApiName":"Task",
						"name":"RequireStatus",
						"active":false,
						"condition":"ISBLANK(Status)",
						"errorMessage":"Status is required"
					}
				]}`),
			}},
		},
	}
	pack, err := NewSourceBackedPack(source)
	if err != nil {
		t.Fatalf("NewSourceBackedPack: %v", err)
	}
	return pack
}

func TestVerifyPersistedRuntimeDeclarationAgainstPackRejectsLegacyProjectionBridgeForOtherRows(t *testing.T) {
	pack := runtimeStartupShallowPersistedCompatPack{}
	startupShallowJSON, err := marshalRuntimeStartupShallowDeclaredRows([]runtimeStartupShallowDeclaredRow{
		{Kind: ComponentKindReportType, BusinessKey: "IssueReport"},
	})
	if err != nil {
		t.Fatalf("marshalRuntimeStartupShallowDeclaredRows: %v", err)
	}
	err = VerifyPersistedRuntimeDeclarationAgainstPack(pack.Name(), `[]`, `[]`, `[]`, startupShallowJSON, pack)
	if err == nil || !strings.Contains(err.Error(), "persisted runtime declaration does not match source identity") {
		t.Fatalf("VerifyPersistedRuntimeDeclarationAgainstPack error = %v, want drift error", err)
	}
}
