package permissions

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"strings"
	"testing"

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

func TestCustomPermissionLifecycleCreatesOnceAndRevivesStableIdentity(t *testing.T) {
	_, lifecycle, err := NewCustomPermissionManagedLifecycleRegistration()
	if err != nil {
		t.Fatal(err)
	}
	request := cp.NewComponentManagedItemLifecycleRequest(customPermissionManagedRequestForTest(t))
	store := newPermissionSetDefinitionLifecycleMemoryStore()

	plan, err := lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeItem, request, store)
	if err != nil {
		t.Fatal(err)
	}
	result, err := lifecycle.Lifecycle().Mutate(context.Background(), cp.ComponentManagedScopeItem, request, plan, store)
	if err != nil {
		t.Fatal(err)
	}
	if result.Disposition != cp.ComponentManagedMutationDesiredProjectionStaged {
		t.Fatalf("create disposition = %q", result.Disposition)
	}
	projection, err := lifecycle.Lifecycle().Project(context.Background(), cp.ComponentManagedScopeItem, request, store)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(projection.Expected, projection.Live) {
		t.Fatalf("created projection differs:\n%s\n%s", projection.Expected, projection.Live)
	}
	created := customPermissionRowForTest(t, store, "SendRecordEmail")
	createdID := created["Id"]
	created["IsDeleted"] = true
	projection, err = lifecycle.Lifecycle().Project(context.Background(), cp.ComponentManagedScopeItem, request, store)
	if err != nil {
		t.Fatal(err)
	}
	if bytes.Equal(projection.Expected, projection.Live) {
		t.Fatal("soft-deleted custom permission must not satisfy the live projection")
	}
	created["IsDeleted"] = false

	store.resetMutations()
	plan, err = lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeItem, request, store)
	if err != nil {
		t.Fatal(err)
	}
	result, err = lifecycle.Lifecycle().Mutate(context.Background(), cp.ComponentManagedScopeItem, request, plan, store)
	if err != nil {
		t.Fatal(err)
	}
	if result.Disposition != cp.ComponentManagedMutationNoChange || len(store.inserts)+len(store.updates) != 0 {
		t.Fatalf("reapply disposition/mutations = %q/%d", result.Disposition, len(store.inserts)+len(store.updates))
	}

	created["Label"] = "Stale"
	created["IsActive"] = false
	created["IsDeleted"] = true
	store.resetMutations()
	plan, err = lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeItem, request, store)
	if err != nil {
		t.Fatal(err)
	}
	result, err = lifecycle.Lifecycle().Mutate(context.Background(), cp.ComponentManagedScopeItem, request, plan, store)
	if err != nil {
		t.Fatal(err)
	}
	revived := customPermissionRowForTest(t, store, "SendRecordEmail")
	if result.Disposition != cp.ComponentManagedMutationDesiredProjectionStaged ||
		revived["Id"] != createdID ||
		revived["Label"] != "Send Record Email" ||
		revived["IsActive"] != true ||
		revived["IsDeleted"] != false {
		t.Fatalf("revived result/row = %q/%#v", result.Disposition, revived)
	}
}

func TestCustomPermissionLifecyclePreservesCustomizedRow(t *testing.T) {
	_, lifecycle, err := NewCustomPermissionManagedLifecycleRegistration()
	if err != nil {
		t.Fatal(err)
	}
	request := cp.NewComponentManagedItemLifecycleRequest(customPermissionManagedRequestForTest(t))
	store := newPermissionSetDefinitionLifecycleMemoryStore()
	store.rows["_System_CustomPermission"] = []cp.ComponentRow{{
		"Id":           "customized-custom-permission",
		"ApiName":      "SendRecordEmail",
		"Label":        "Administrator Label",
		"Description":  "Administrator description",
		"IsActive":     true,
		"IsDeleted":    false,
		"IsCustomized": true,
		"OwnerPack":    "salesforce-crm-standard",
	}}

	plan, err := lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeItem, request, store)
	if err != nil {
		t.Fatal(err)
	}
	result, err := lifecycle.Lifecycle().Mutate(context.Background(), cp.ComponentManagedScopeItem, request, plan, store)
	if err != nil {
		t.Fatal(err)
	}
	if result.Disposition != cp.ComponentManagedMutationNoChange || len(store.inserts)+len(store.updates) != 0 {
		t.Fatalf("customized reapply disposition/mutations = %q/%d", result.Disposition, len(store.inserts)+len(store.updates))
	}
	row := customPermissionRowForTest(t, store, "SendRecordEmail")
	if row["Label"] != "Administrator Label" || row["Description"] != "Administrator description" || row["IsCustomized"] != true {
		t.Fatalf("customized row was overwritten: %#v", row)
	}
	projection, err := lifecycle.Lifecycle().Project(context.Background(), cp.ComponentManagedScopeItem, request, store)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(projection.Expected, projection.Live) {
		t.Fatalf("healthy customized projection differs:\n%s\n%s", projection.Expected, projection.Live)
	}

	row["IsActive"] = false
	store.resetMutations()
	plan, err = lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeItem, request, store)
	if err != nil {
		t.Fatal(err)
	}
	result, err = lifecycle.Lifecycle().Mutate(context.Background(), cp.ComponentManagedScopeItem, request, plan, store)
	if err != nil {
		t.Fatal(err)
	}
	if result.Disposition != cp.ComponentManagedMutationNoChange || len(store.inserts)+len(store.updates) != 0 {
		t.Fatalf("inactive customized disposition/mutations = %q/%d", result.Disposition, len(store.inserts)+len(store.updates))
	}
	projection, err = lifecycle.Lifecycle().Project(context.Background(), cp.ComponentManagedScopeItem, request, store)
	if err != nil {
		t.Fatal(err)
	}
	if bytes.Equal(projection.Expected, projection.Live) {
		t.Fatal("inactive customized row must be preserved but fail verification")
	}
	if row["Label"] != "Administrator Label" || row["Description"] != "Administrator description" || row["IsCustomized"] != true {
		t.Fatalf("inactive customized row was overwritten: %#v", row)
	}
}

func TestCustomPermissionLifecycleItemFitsTransactionReadBudget(t *testing.T) {
	_, lifecycle, err := NewCustomPermissionManagedLifecycleRegistration()
	if err != nil {
		t.Fatal(err)
	}
	request := cp.NewComponentManagedItemLifecycleRequest(customPermissionManagedRequestForTest(t))
	store := newPermissionSetDefinitionLifecycleMemoryStore()
	store.rows["_System_CustomPermission"] = []cp.ComponentRow{{
		"Id":           "managed-custom-permission",
		"ApiName":      "SendRecordEmail",
		"Label":        "Send Record Email",
		"Description":  "Allows the standard email action.",
		"IsActive":     true,
		"IsDeleted":    false,
		"IsCustomized": false,
		"OwnerPack":    "salesforce-crm-standard",
	}}
	metered := &permissionSetDefinitionLifecycleMeteredStore{
		permissionSetDefinitionLifecycleMemoryStore: store,
		maximumCurrentItems:                         lifecycle.Budget().MaxCurrentItems,
	}

	// Include a separate preflight read as a conservative item-path proof. The
	// host meters preflight independently from locked Plan/Mutate/Project.
	if _, err := lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeItem, request, metered); err != nil {
		t.Fatalf("ambient plan: %v", err)
	}
	plan, err := lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeItem, request, metered)
	if err != nil {
		t.Fatalf("locked plan: %v", err)
	}
	if _, err := lifecycle.Lifecycle().Mutate(context.Background(), cp.ComponentManagedScopeItem, request, plan, metered); err != nil {
		t.Fatalf("mutation after %d current items: %v", metered.currentItems, err)
	}
	if _, err := lifecycle.Lifecycle().Project(context.Background(), cp.ComponentManagedScopeItem, request, metered); err != nil {
		t.Fatalf("projection after %d current items: %v", metered.currentItems, err)
	}
	if metered.currentItems != 4 || metered.currentItems > lifecycle.Budget().MaxCurrentItems {
		t.Fatalf("item current items = %d, budget = %d", metered.currentItems, lifecycle.Budget().MaxCurrentItems)
	}
}

func TestCustomPermissionLifecycleRejectsOwnerlessOrForeignCollision(t *testing.T) {
	_, lifecycle, err := NewCustomPermissionManagedLifecycleRegistration()
	if err != nil {
		t.Fatal(err)
	}
	request := cp.NewComponentManagedItemLifecycleRequest(customPermissionManagedRequestForTest(t))

	for _, ownerPack := range []any{nil, "", "another-pack"} {
		t.Run(ownerPackNameForTest(ownerPack), func(t *testing.T) {
			store := newPermissionSetDefinitionLifecycleMemoryStore()
			store.rows["_System_CustomPermission"] = []cp.ComponentRow{{
				"Id":           "existing-custom-permission",
				"ApiName":      "SendRecordEmail",
				"Label":        "Existing",
				"Description":  nil,
				"IsActive":     true,
				"IsDeleted":    false,
				"IsCustomized": false,
				"OwnerPack":    ownerPack,
			}}

			if _, err := lifecycle.Lifecycle().Plan(
				context.Background(),
				cp.ComponentManagedScopeItem,
				request,
				store,
			); err == nil || !strings.Contains(err.Error(), "cannot claim") {
				t.Fatalf("Plan() error = %v, want owner collision", err)
			}
			if _, err := lifecycle.Lifecycle().Project(
				context.Background(),
				cp.ComponentManagedScopeItem,
				request,
				store,
			); err == nil || !strings.Contains(err.Error(), "cannot claim") {
				t.Fatalf("Project() error = %v, want owner collision", err)
			}
		})
	}
}

func TestCustomPermissionLifecycleRejectsOverlongOwnerPackBeforeRead(t *testing.T) {
	_, lifecycle, err := NewCustomPermissionManagedLifecycleRegistration()
	if err != nil {
		t.Fatal(err)
	}
	request := customPermissionManagedRequestForTest(t)
	request.PackName = strings.Repeat("p", customPermissionMaximumOwnerPackBytes+1)
	store := newPermissionSetDefinitionLifecycleMemoryStore()

	if _, err := lifecycle.Lifecycle().Plan(
		context.Background(),
		cp.ComponentManagedScopeItem,
		cp.NewComponentManagedItemLifecycleRequest(request),
		store,
	); err == nil || !strings.Contains(err.Error(), "1..64 bytes") {
		t.Fatalf("Plan() error = %v, want owner-pack storage limit", err)
	}
	if len(store.reads) != 0 {
		t.Fatalf("overlong owner pack reached storage reads: %#v", store.reads)
	}
}

func TestCustomPermissionLifecycleReconcilesExactOwnerSet(t *testing.T) {
	_, lifecycle, err := NewCustomPermissionManagedLifecycleRegistration()
	if err != nil {
		t.Fatal(err)
	}
	itemRequest := cp.NewComponentManagedItemLifecycleRequest(customPermissionManagedRequestForTest(t))
	store := newPermissionSetDefinitionLifecycleMemoryStore()
	store.rows["_System_CustomPermission"] = nil

	itemPlan, err := lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeItem, itemRequest, store)
	if err != nil {
		t.Fatal(err)
	}
	if _, err := lifecycle.Lifecycle().Mutate(context.Background(), cp.ComponentManagedScopeItem, itemRequest, itemPlan, store); err != nil {
		t.Fatal(err)
	}
	createdID := customPermissionRowForTest(t, store, "SendRecordEmail")["Id"]
	store.rows["_System_CustomPermission"] = append(store.rows["_System_CustomPermission"], customPermissionLifecycleRowForTest(
		"stale-custom-permission",
		"RetiredBySource",
		"salesforce-crm-standard",
	))

	setRequest := customPermissionSetRequestForTest(t, []string{"SendRecordEmail"})
	setPlan, err := lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeSet, setRequest, store)
	if err != nil {
		t.Fatal(err)
	}
	result, err := lifecycle.Lifecycle().Mutate(context.Background(), cp.ComponentManagedScopeSet, setRequest, setPlan, store)
	if err != nil {
		t.Fatal(err)
	}
	stale := customPermissionRowForTest(t, store, "RetiredBySource")
	if result.Disposition != cp.ComponentManagedMutationDesiredProjectionStaged ||
		stale["Id"] != "stale-custom-permission" || stale["IsActive"] != false || stale["IsDeleted"] != true {
		t.Fatalf("retirement result/row = %q/%#v", result.Disposition, stale)
	}
	if customPermissionRowForTest(t, store, "SendRecordEmail")["Id"] != createdID {
		t.Fatal("exact-set reconciliation replaced the retained stable identity")
	}
	projection, err := lifecycle.Lifecycle().Project(context.Background(), cp.ComponentManagedScopeSet, setRequest, store)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(projection.Expected, projection.Live) {
		t.Fatalf("reconciled set projection differs:\nexpected %s\nlive %s", projection.Expected, projection.Live)
	}

	store.resetMutations()
	setPlan, err = lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeSet, setRequest, store)
	if err != nil {
		t.Fatal(err)
	}
	result, err = lifecycle.Lifecycle().Mutate(context.Background(), cp.ComponentManagedScopeSet, setRequest, setPlan, store)
	if err != nil {
		t.Fatal(err)
	}
	if result.Disposition != cp.ComponentManagedMutationNoChange || len(store.updates) != 0 {
		t.Fatalf("second reconcile disposition/updates = %q/%d", result.Disposition, len(store.updates))
	}
}

func TestCustomPermissionLifecycleExactSetPreservesCustomizedOwnerRows(t *testing.T) {
	for _, tt := range []struct {
		name    string
		active  bool
		deleted bool
	}{
		{name: "active", active: true, deleted: false},
		{name: "administrator deactivated", active: false, deleted: false},
		{name: "administrator deleted", active: false, deleted: true},
	} {
		t.Run(tt.name, func(t *testing.T) {
			_, lifecycle, err := NewCustomPermissionManagedLifecycleRegistration()
			if err != nil {
				t.Fatal(err)
			}
			store := newPermissionSetDefinitionLifecycleMemoryStore()
			customized := customPermissionLifecycleRowForTest(
				"customized-custom-permission",
				"AdministratorOwned",
				"salesforce-crm-standard",
			)
			customized["IsCustomized"] = true
			customized["IsActive"] = tt.active
			customized["IsDeleted"] = tt.deleted
			customized["Label"] = "Administrator label"
			store.rows["_System_CustomPermission"] = []cp.ComponentRow{customized}
			request := customPermissionSetRequestForTest(t, nil)

			plan, err := lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeSet, request, store)
			if err != nil {
				t.Fatal(err)
			}
			result, err := lifecycle.Lifecycle().Mutate(context.Background(), cp.ComponentManagedScopeSet, request, plan, store)
			if err != nil {
				t.Fatal(err)
			}
			if result.Disposition != cp.ComponentManagedMutationNoChange || len(store.updates) != 0 {
				t.Fatalf("customized exact-set result/updates = %q/%d, want no change", result.Disposition, len(store.updates))
			}
			row := customPermissionRowForTest(t, store, "AdministratorOwned")
			if row["IsActive"] != tt.active || row["IsDeleted"] != tt.deleted || row["Label"] != "Administrator label" {
				t.Fatalf("exact-set reconciliation changed customized row: %#v", row)
			}
			projection, err := lifecycle.Lifecycle().Project(context.Background(), cp.ComponentManagedScopeSet, request, store)
			if err != nil {
				t.Fatal(err)
			}
			if !bytes.Equal(projection.Expected, projection.Live) {
				t.Fatalf("customized row leaked into managed set projection: expected %s live %s", projection.Expected, projection.Live)
			}
		})
	}
}

func TestCustomPermissionLifecycleExactSetCountsCustomizedDeclaredRow(t *testing.T) {
	_, lifecycle, err := NewCustomPermissionManagedLifecycleRegistration()
	if err != nil {
		t.Fatal(err)
	}
	store := newPermissionSetDefinitionLifecycleMemoryStore()
	customized := customPermissionLifecycleRowForTest(
		"customized-custom-permission",
		"AdministratorOwned",
		"salesforce-crm-standard",
	)
	customized["IsCustomized"] = true
	customized["Label"] = "Administrator label"
	store.rows["_System_CustomPermission"] = []cp.ComponentRow{customized}
	request := customPermissionSetRequestForTest(t, []string{"AdministratorOwned"})

	plan, err := lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeSet, request, store)
	if err != nil {
		t.Fatal(err)
	}
	result, err := lifecycle.Lifecycle().Mutate(context.Background(), cp.ComponentManagedScopeSet, request, plan, store)
	if err != nil {
		t.Fatal(err)
	}
	if result.Disposition != cp.ComponentManagedMutationNoChange || len(store.updates) != 0 {
		t.Fatalf("declared customized exact-set result/updates = %q/%d, want no change", result.Disposition, len(store.updates))
	}
	projection, err := lifecycle.Lifecycle().Project(context.Background(), cp.ComponentManagedScopeSet, request, store)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(projection.Expected, projection.Live) {
		t.Fatalf("declared customized row missing from managed set projection: expected %s live %s", projection.Expected, projection.Live)
	}
}

func TestCustomPermissionLifecycleOwnerSetRejectsCollatedForeignOwner(t *testing.T) {
	_, lifecycle, err := NewCustomPermissionManagedLifecycleRegistration()
	if err != nil {
		t.Fatal(err)
	}
	for _, ownerPack := range []string{"Salesforce-CRM-Standard", "salesforce-crm-standard "} {
		t.Run(ownerPackNameForTest(ownerPack), func(t *testing.T) {
			store := &customPermissionCollatedOwnerReadStore{row: customPermissionLifecycleRowForTest(
				"collated-foreign-owner",
				"ForeignUnderCollation",
				ownerPack,
			)}
			_, err := lifecycle.Lifecycle().Plan(
				context.Background(),
				cp.ComponentManagedScopeSet,
				customPermissionSetRequestForTest(t, nil),
				store,
			)
			if err == nil || !strings.Contains(err.Error(), "does not exactly match") {
				t.Fatalf("collated foreign owner Plan() error = %v, want exact-owner rejection", err)
			}
		})
	}
}

func TestCustomPermissionLifecycleRejectsReferencedRetirementAtPreflightAndLockedReplan(t *testing.T) {
	for _, grant := range []struct {
		table  string
		parent string
	}{
		{table: "PermissionSetCustomPermission", parent: "PermissionSetId"},
		{table: "ProfileCustomPermission", parent: "ProfileId"},
	} {
		t.Run(grant.table, func(t *testing.T) {
			_, lifecycle, err := NewCustomPermissionManagedLifecycleRegistration()
			if err != nil {
				t.Fatal(err)
			}
			store := newPermissionSetDefinitionLifecycleMemoryStore()
			store.rows["_System_CustomPermission"] = []cp.ComponentRow{
				customPermissionLifecycleRowForTest("referenced-custom-permission", "ReferencedByGrant", "salesforce-crm-standard"),
			}
			grantRow := cp.ComponentRow{
				"Id":                 "custom-permission-grant",
				"CustomPermissionId": "referenced-custom-permission",
				grant.parent:         "grant-parent",
			}
			store.rows[grant.table] = []cp.ComponentRow{grantRow}
			request := customPermissionSetRequestForTest(t, nil)

			if _, err := lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeSet, request, store); err == nil ||
				!strings.Contains(err.Error(), grant.table) || !strings.Contains(err.Error(), "referenced") {
				t.Fatalf("referenced Plan() error = %v", err)
			}

			store.rows[grant.table] = nil
			plan, err := lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeSet, request, store)
			if err != nil {
				t.Fatal(err)
			}
			store.rows[grant.table] = []cp.ComponentRow{grantRow}
			if _, err := lifecycle.Lifecycle().Mutate(context.Background(), cp.ComponentManagedScopeSet, request, plan, store); err == nil ||
				!strings.Contains(err.Error(), grant.table) || !strings.Contains(err.Error(), "referenced") {
				t.Fatalf("referenced Mutate() error = %v", err)
			}
			if len(store.locks) == 0 || store.locks[0].Table != "_System_CustomPermission" ||
				store.locks[len(store.locks)-1].Table != grant.table {
				t.Fatalf("retirement lock order = %#v", store.locks)
			}
			row := customPermissionRowForTest(t, store, "ReferencedByGrant")
			if row["IsActive"] != true || row["IsDeleted"] != false || len(store.updates) != 0 {
				t.Fatalf("rejected retirement changed row: %#v", row)
			}
			row["IsActive"] = false
			row["IsDeleted"] = true
			if _, err := lifecycle.Lifecycle().Project(context.Background(), cp.ComponentManagedScopeSet, request, store); err == nil ||
				!strings.Contains(err.Error(), grant.table) || !strings.Contains(err.Error(), "referenced") {
				t.Fatalf("referenced retired Project() error = %v", err)
			}
		})
	}
}

func TestCustomPermissionLifecycleProjectsUnretiredOwnerMemberAsSetDrift(t *testing.T) {
	_, lifecycle, err := NewCustomPermissionManagedLifecycleRegistration()
	if err != nil {
		t.Fatal(err)
	}
	store := newPermissionSetDefinitionLifecycleMemoryStore()
	store.rows["_System_CustomPermission"] = []cp.ComponentRow{
		customPermissionLifecycleRowForTest("stale-custom-permission", "StaleMember", "salesforce-crm-standard"),
	}
	request := customPermissionSetRequestForTest(t, nil)
	projection, err := lifecycle.Lifecycle().Project(context.Background(), cp.ComponentManagedScopeSet, request, store)
	if err != nil {
		t.Fatal(err)
	}
	if bytes.Equal(projection.Expected, projection.Live) || !bytes.Contains(projection.Live, []byte("StaleMember")) {
		t.Fatalf("set projection expected/live = %s / %s, want stale member only in live", projection.Expected, projection.Live)
	}
}

func TestCustomPermissionLifecycleSetFitsMaximumTransactionReadBudget(t *testing.T) {
	_, lifecycle, err := NewCustomPermissionManagedLifecycleRegistration()
	if err != nil {
		t.Fatal(err)
	}
	store := newPermissionSetDefinitionLifecycleMemoryStore()
	store.rows["_System_CustomPermission"] = nil
	keys := make([]string, customPermissionManagedMaximumRows)
	for index := range keys {
		keys[index] = fmt.Sprintf("CustomPermission_%03d", index)
		store.rows["_System_CustomPermission"] = append(store.rows["_System_CustomPermission"], customPermissionLifecycleRowForTest(
			fmt.Sprintf("custom-permission-%03d", index),
			keys[index],
			"salesforce-crm-standard",
		))
	}
	request := customPermissionSetRequestForTest(t, keys)
	metered := &permissionSetDefinitionLifecycleMeteredStore{
		permissionSetDefinitionLifecycleMemoryStore: store,
		maximumCurrentItems:                         lifecycle.Budget().MaxCurrentItems,
	}
	plan, err := lifecycle.Lifecycle().Plan(context.Background(), cp.ComponentManagedScopeSet, request, metered)
	if err != nil {
		t.Fatal(err)
	}
	result, err := lifecycle.Lifecycle().Mutate(context.Background(), cp.ComponentManagedScopeSet, request, plan, metered)
	if err != nil {
		t.Fatal(err)
	}
	if result.Disposition != cp.ComponentManagedMutationNoChange {
		t.Fatalf("maximum-set disposition = %q", result.Disposition)
	}
	if _, err := lifecycle.Lifecycle().Project(context.Background(), cp.ComponentManagedScopeSet, request, metered); err != nil {
		t.Fatal(err)
	}
	if metered.currentItems != lifecycle.Budget().MaxCurrentItems {
		t.Fatalf("maximum-set current items = %d, budget = %d", metered.currentItems, lifecycle.Budget().MaxCurrentItems)
	}
}

func TestCustomPermissionLifecycleSetBudgetsDisjointCurrentAndDesiredTargets(t *testing.T) {
	_, lifecycle, err := NewCustomPermissionManagedLifecycleRegistration()
	if err != nil {
		t.Fatal(err)
	}
	store := newPermissionSetDefinitionLifecycleMemoryStore()
	store.rows["_System_CustomPermission"] = nil
	desired := make([]string, customPermissionManagedMaximumRows)
	for index := range desired {
		desired[index] = fmt.Sprintf("DesiredCustomPermission_%03d", index)
		store.rows["_System_CustomPermission"] = append(store.rows["_System_CustomPermission"], customPermissionLifecycleRowForTest(
			fmt.Sprintf("current-custom-permission-%03d", index),
			fmt.Sprintf("CurrentCustomPermission_%03d", index),
			"salesforce-crm-standard",
		))
	}
	plan, err := lifecycle.Lifecycle().Plan(
		context.Background(),
		cp.ComponentManagedScopeSet,
		customPermissionSetRequestForTest(t, desired),
		store,
	)
	if err != nil {
		t.Fatal(err)
	}
	if got, want := len(plan.Targets()), lifecycle.Budget().MaxTargets; got != want {
		t.Fatalf("disjoint set targets = %d, budget = %d", got, want)
	}
}

func customPermissionManagedRequestForTest(t *testing.T) cp.ComponentManagedRequest {
	t.Helper()
	base, _, err := NewCustomPermissionManagedLifecycleRegistration()
	if err != nil {
		t.Fatal(err)
	}
	payload := []byte(`{"schema":"nexuscrm.custom-permission/v1","label":"Send Record Email","description":"Allows the standard email action.","active":true}`)
	build := &permissionSetDefinitionBuildContext{packName: "salesforce-crm-standard"}
	component := cp.ManifestComponent{
		Kind:          customPermissionComponentKind,
		BusinessKey:   "SendRecordEmail",
		Manageability: cp.ManageabilityLocked,
		Payload:       append(json.RawMessage(nil), payload...),
	}
	if err := base.BuildHandler(build, cp.ComponentBuildRequest{
		PackName:  build.packName,
		Component: component,
		Payload:   payload,
	}); err != nil {
		t.Fatal(err)
	}
	return cp.ComponentManagedRequest{
		PackName:           build.packName,
		Component:          component,
		Payload:            payload,
		ExpectedProjection: build.managed[0].ExpectedProjection,
	}
}

func customPermissionSetRequestForTest(t *testing.T, desired []string) cp.ComponentManagedLifecycleRequest {
	t.Helper()
	request, err := cp.NewComponentManagedSetLifecycleRequest(cp.ComponentManagedSetRequest{
		PackName: "salesforce-crm-standard",
		Kind:     customPermissionComponentKind,
	}, desired)
	if err != nil {
		t.Fatal(err)
	}
	return request
}

func customPermissionLifecycleRowForTest(id, apiName, ownerPack string) cp.ComponentRow {
	return cp.ComponentRow{
		"Id":           id,
		"ApiName":      apiName,
		"Label":        apiName,
		"Description":  nil,
		"IsActive":     true,
		"IsDeleted":    false,
		"IsCustomized": false,
		"OwnerPack":    ownerPack,
	}
}

func customPermissionRowForTest(t *testing.T, store *permissionSetDefinitionLifecycleMemoryStore, apiName string) cp.ComponentRow {
	t.Helper()
	for _, row := range store.rows["_System_CustomPermission"] {
		if row["ApiName"] == apiName {
			return row
		}
	}
	t.Fatalf("custom permission %s was not found", apiName)
	return nil
}

func ownerPackNameForTest(value any) string {
	if value == nil {
		return "null"
	}
	if value == "" {
		return "empty"
	}
	return value.(string)
}

// customPermissionCollatedOwnerReadStore models a database collation that can
// return case- or trailing-space-equivalent OwnerPack values for an equality
// predicate. The provider must still validate the stored bytes exactly.
type customPermissionCollatedOwnerReadStore struct {
	row cp.ComponentRow
}

func (s *customPermissionCollatedOwnerReadStore) ReadRows(
	_ context.Context,
	query cp.ComponentManagedRowQuery,
) ([]cp.ComponentRow, error) {
	if query.Table != "_System_CustomPermission" {
		return nil, nil
	}
	row := make(cp.ComponentRow, len(query.Columns))
	for _, column := range query.Columns {
		if value, ok := s.row[column]; ok {
			row[column] = value
		}
	}
	return []cp.ComponentRow{row}, nil
}
