package sfcrmappservice

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"

	catalogsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/catalog/consumerv1"
	commonsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/commonv1"
	permissionauthoringsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/permissionauthoringv1"
)

const maxCatalogRevision = ^uint64(0)

func permissionAuthoringReceipts(revision uint64) commonsemantic.Receipts {
	return commonsemantic.Receipts{
		ProtocolVersion: "1.0", CatalogRevision: revision, SchemaGeneration: 2,
		EngineGeneration: 3, SecurityEpoch: 4,
		CapabilityVersion: permissionauthoringsemantic.CapabilityName,
	}
}

func permissionAuthoringHTTPTestService(t *testing.T) (*Service, *permissionAuthoringHTTPCalls) {
	t.Helper()
	calls := &permissionAuthoringHTTPCalls{snapshotSystemEnabled: true}
	service := newTestService(t, &fakeRuntime{})
	standardObject := "standard_object"
	view := searchTestView(t, []searchObjectSpec{{
		APIName: "Account", Label: "Account", TableType: &standardObject, Fields: []searchFieldSpec{
			{APIName: "Name", Label: "Account Name", Type: "string"},
			{APIName: "Secret__c", Label: "Secret", Type: "string"},
		},
	}})
	view.EffectiveComponents[0].ComponentFormatVersion = effectiveObjectSearchComponentFormatV5
	view.Lineage.CatalogRevision = maxCatalogRevision
	view.Receipts.CatalogRevision = maxCatalogRevision
	view.Lineage.ViewDigest = catalogsemantic.ComputeAppMetadataViewV3Digest(view)
	if err := catalogsemantic.ValidateAppMetadataViewV3(view); err != nil {
		t.Fatal(err)
	}
	specs, err := searchObjectSpecsFromView(view)
	if err != nil {
		t.Fatalf("permission authoring AppMetadata fixture is not consumable: %v", err)
	}
	if _, err := permissionResourceTypes(specs); err != nil {
		t.Fatalf("permission authoring AppMetadata fixture is not current: %v", err)
	}
	service.appMetadataV3 = func(_ context.Context, request catalogsemantic.GetRequest) (catalogsemantic.AppMetadataViewV3, error) {
		if request.MinCatalogRevision != nil && *request.MinCatalogRevision > view.Receipts.CatalogRevision {
			t.Fatalf("AppMetadata minimum revision = %d, served = %d", *request.MinCatalogRevision, view.Receipts.CatalogRevision)
		}
		return view, nil
	}
	client, err := NewRuntimePermissionAuthoringClient(
		func(_ context.Context, bearer string, request permissionauthoringsemantic.SnapshotRequest) (permissionauthoringsemantic.SnapshotResponse, error) {
			calls.snapshotBearer, calls.snapshot = bearer, request
			calls.snapshotCount++
			if calls.snapshotErr != nil {
				return permissionauthoringsemantic.SnapshotResponse{}, calls.snapshotErr
			}
			token, err := permissionauthoringsemantic.NewAuthoringToken("permission-set-1", 8)
			if err != nil {
				t.Fatal(err)
			}
			response := permissionauthoringsemantic.SnapshotResponse{
				CanonicalPermissionSetID: "permission-set-1", AuthoringToken: token,
				Receipts: permissionAuthoringReceipts(maxCatalogRevision),
			}
			if !calls.emptySnapshot {
				response.Catalog.System = []permissionauthoringsemantic.SystemPermission{{PermissionID: "ViewSetup", Label: "View Setup", Category: "Administration"}}
				response.Grants.System = []permissionauthoringsemantic.CapabilityGrant{{CapabilityID: "ViewSetup", Enabled: calls.snapshotSystemEnabled}}
			}
			return permissionauthoringsemantic.NormalizeSnapshotResponse(response), nil
		},
		func(ctx context.Context, bearer string, request permissionauthoringsemantic.Request) (permissionauthoringsemantic.Response, error) {
			calls.saveBearer, calls.save = bearer, request
			calls.saveCount++
			if calls.saveWaitForContext {
				<-ctx.Done()
				return permissionauthoringsemantic.Response{}, ctx.Err()
			}
			if calls.saveCount == 1 && calls.saveErr != nil {
				return permissionauthoringsemantic.Response{}, calls.saveErr
			}
			if calls.replayRejected {
				return permissionAuthoringRejectedResponse(t, request), nil
			}
			return permissionAuthoringAppliedResponse(t, request), nil
		},
		func(ctx context.Context, bearer string, request permissionauthoringsemantic.Request) (permissionauthoringsemantic.StatusResponse, error) {
			calls.statusBearer, calls.status = bearer, request
			calls.statusCount++
			calls.statusContextErr = ctx.Err()
			calls.statusDeadline, _ = ctx.Deadline()
			if calls.statusErr != nil {
				return permissionauthoringsemantic.StatusResponse{}, calls.statusErr
			}
			digest, err := permissionauthoringsemantic.CommandDigest(request)
			if err != nil {
				t.Fatal(err)
			}
			if calls.statusCount <= calls.statusAcceptedCount {
				return permissionauthoringsemantic.StatusResponse{
					CommandID: request.CommandID, CommandDigest: digest,
					State: permissionauthoringsemantic.CommandAccepted,
				}, nil
			}
			result := permissionAuthoringAppliedResponse(t, request)
			return permissionauthoringsemantic.StatusResponse{
				CommandID: request.CommandID, CommandDigest: digest,
				State: permissionauthoringsemantic.CommandCompleted, Result: &result,
			}, nil
		},
	)
	if err != nil {
		t.Fatal(err)
	}
	service.permissionAuthoring = client
	return service, calls
}

type permissionAuthoringHTTPCalls struct {
	snapshotBearer        string
	snapshot              permissionauthoringsemantic.SnapshotRequest
	snapshotCount         int
	snapshotErr           error
	emptySnapshot         bool
	snapshotSystemEnabled bool
	saveBearer            string
	save                  permissionauthoringsemantic.Request
	saveCount             int
	saveWaitForContext    bool
	statusBearer          string
	status                permissionauthoringsemantic.Request
	statusCount           int
	statusContextErr      error
	statusDeadline        time.Time
	saveErr               error
	statusErr             error
	statusAcceptedCount   int
	replayRejected        bool
}

func permissionAuthoringAppliedResponse(t *testing.T, request permissionauthoringsemantic.Request) permissionauthoringsemantic.Response {
	t.Helper()
	digest, err := permissionauthoringsemantic.CommandDigest(request)
	if err != nil {
		t.Fatal(err)
	}
	token, err := permissionauthoringsemantic.NewAuthoringToken("permission-set-1", 9)
	if err != nil {
		t.Fatal(err)
	}
	return permissionauthoringsemantic.Response{
		CommandID: request.CommandID, CommandDigest: digest,
		Outcome:                  permissionauthoringsemantic.OutcomeApplied,
		CanonicalPermissionSetID: "permission-set-1", AuthoringToken: token,
		Receipts:            permissionAuthoringReceipts(maxCatalogRevision),
		OutcomeExpiresAtUTC: "2030-01-02T03:04:05Z",
	}
}

func permissionAuthoringRejectedResponse(t *testing.T, request permissionauthoringsemantic.Request) permissionauthoringsemantic.Response {
	t.Helper()
	digest, err := permissionauthoringsemantic.CommandDigest(request)
	if err != nil {
		t.Fatal(err)
	}
	return permissionauthoringsemantic.Response{
		CommandID: request.CommandID, CommandDigest: digest,
		Outcome: permissionauthoringsemantic.OutcomeRejected, RejectionCode: permissionauthoringsemantic.RejectionDenied,
		Receipts: permissionAuthoringReceipts(maxCatalogRevision), OutcomeExpiresAtUTC: "2030-01-02T03:04:05Z",
	}
}

func permissionAuthoringHTTPRequest(path, body string) *http.Request {
	request := httptest.NewRequest(http.MethodPost, path, strings.NewReader(body))
	request.Header.Set("Authorization", "Bearer user-secret")
	return request
}

func TestPermissionAuthoringHTTPPreservesProfileAndCatalogFence(t *testing.T) {
	service, calls := permissionAuthoringHTTPTestService(t)
	snapshotRecorder := httptest.NewRecorder()
	service.ServeHTTP(snapshotRecorder, permissionAuthoringHTTPRequest(PermissionAuthoringSnapshotPath, `{"target":{"type":"profile","id":"profile-1"}}`))
	if snapshotRecorder.Code != http.StatusOK || calls.snapshotBearer != "user-secret" ||
		calls.snapshot.Target.Kind != permissionauthoringsemantic.TargetProfile || calls.snapshot.Target.ID != "profile-1" {
		t.Fatalf("Snapshot status=%d request=%+v body=%s", snapshotRecorder.Code, calls.snapshot, snapshotRecorder.Body.String())
	}
	var snapshotBody struct {
		CanonicalPermissionSetID string `json:"canonicalPermissionSetId"`
		AuthoringToken           string `json:"authoringToken"`
		CatalogRevision          string `json:"catalogRevision"`
		Catalog                  struct {
			Objects []permissionAuthoringObjectCatalogDTO `json:"objects"`
		} `json:"catalog"`
	}
	if err := json.Unmarshal(snapshotRecorder.Body.Bytes(), &snapshotBody); err != nil ||
		snapshotBody.CanonicalPermissionSetID != "permission-set-1" || snapshotBody.CatalogRevision != "18446744073709551615" ||
		len(snapshotBody.Catalog.Objects) != 1 || snapshotBody.Catalog.Objects[0].ResourceType != "Account" {
		t.Fatalf("Snapshot projection = %+v, %v", snapshotBody, err)
	}

	body := fmt.Sprintf(`{"commandId":"permission-authoring:command-1","target":{"type":"profile","id":"profile-1"},"expectedAuthoringToken":%q,"minCatalogRevision":"18446744073709551615","changes":{"system":[{"capabilityId":"ViewSetup","enabled":true}],"objects":[{"resourceType":"Account","read":true,"create":false,"edit":false,"delete":false,"viewAll":false,"modifyAll":false}],"fields":[{"resourceType":"Account","fieldName":"Name","read":true,"edit":false}],"recordTypes":[{"recordTypeId":"record-type-1","resourceType":"Account","visible":true}],"custom":[{"capabilityId":"custom-1","enabled":true}]}}`, snapshotBody.AuthoringToken)
	saveRecorder := httptest.NewRecorder()
	service.ServeHTTP(saveRecorder, permissionAuthoringHTTPRequest(PermissionAuthoringSavePath, body))
	if saveRecorder.Code != http.StatusOK || calls.save.Target.Kind != permissionauthoringsemantic.TargetProfile ||
		calls.save.Target.ID != "profile-1" || calls.save.MinCatalogRevision == nil || *calls.save.MinCatalogRevision != maxCatalogRevision ||
		len(calls.save.Changes.System) != 1 || len(calls.save.Changes.Objects) != 1 || len(calls.save.Changes.Fields) != 1 ||
		len(calls.save.Changes.RecordTypes) != 1 || calls.save.Changes.RecordTypes[0].ResourceType != "Account" ||
		len(calls.save.Changes.Custom) != 1 {
		t.Fatalf("Save status=%d request=%+v body=%s", saveRecorder.Code, calls.save, saveRecorder.Body.String())
	}

	statusRecorder := httptest.NewRecorder()
	service.ServeHTTP(statusRecorder, permissionAuthoringHTTPRequest(PermissionAuthoringStatusPath, `{"command":`+body+`}`))
	if statusRecorder.Code != http.StatusOK || calls.status.CommandID != calls.save.CommandID || calls.status.Target != calls.save.Target ||
		calls.status.ExpectedAuthoringToken != calls.save.ExpectedAuthoringToken {
		t.Fatalf("Status status=%d request=%+v body=%s", statusRecorder.Code, calls.status, statusRecorder.Body.String())
	}
}

func TestPermissionAuthoringStatusReplaysAcceptedCommandUnderSameBearer(t *testing.T) {
	service, calls := permissionAuthoringHTTPTestService(t)
	calls.statusAcceptedCount = 1
	token, err := permissionauthoringsemantic.NewAuthoringToken("permission-set-1", 8)
	if err != nil {
		t.Fatal(err)
	}
	body := fmt.Sprintf(`{"commandId":"permission-authoring:accepted-1","target":{"type":"permissionSet","id":"permission-set-1"},"expectedAuthoringToken":%q,"minCatalogRevision":"18446744073709551615","changes":{"system":[{"capabilityId":"ViewSetup","enabled":true}]}}`, token)
	recorder := httptest.NewRecorder()
	service.ServeHTTP(recorder, permissionAuthoringHTTPRequest(PermissionAuthoringStatusPath, `{"command":`+body+`}`))
	if recorder.Code != http.StatusOK || calls.statusCount != 1 || calls.saveCount != 1 ||
		calls.statusBearer != "user-secret" || calls.saveBearer != "user-secret" || calls.save.CommandID != calls.status.CommandID ||
		!strings.Contains(recorder.Body.String(), `"state":"COMPLETED"`) {
		t.Fatalf("status=%d calls=%d/%d bearers=%q/%q body=%s", recorder.Code, calls.statusCount, calls.saveCount, calls.statusBearer, calls.saveBearer, recorder.Body.String())
	}
	if remaining := time.Until(calls.statusDeadline); calls.statusDeadline.IsZero() || remaining <= 0 || remaining > service.requestTimeout*3/4 {
		t.Fatalf("initial Status did not reserve recovery budget: deadline=%s remaining=%s timeout=%s", calls.statusDeadline, remaining, service.requestTimeout)
	}
}

func TestPermissionAuthoringStatusKeepsAcceptedCommandAfterAmbiguousReplay(t *testing.T) {
	service, calls := permissionAuthoringHTTPTestService(t)
	calls.statusAcceptedCount = 2
	calls.saveErr = &commonsemantic.Failure{Category: commonsemantic.FailureDeadlineExceeded}
	token, err := permissionauthoringsemantic.NewAuthoringToken("permission-set-1", 8)
	if err != nil {
		t.Fatal(err)
	}
	body := fmt.Sprintf(`{"commandId":"permission-authoring:accepted-2","target":{"type":"permissionSet","id":"permission-set-1"},"expectedAuthoringToken":%q,"minCatalogRevision":"18446744073709551615","changes":{"system":[{"capabilityId":"ViewSetup","enabled":true}]}}`, token)
	recorder := httptest.NewRecorder()
	service.ServeHTTP(recorder, permissionAuthoringHTTPRequest(PermissionAuthoringStatusPath, `{"command":`+body+`}`))
	if recorder.Code != http.StatusOK || calls.statusCount != 2 || calls.saveCount != 1 ||
		!strings.Contains(recorder.Body.String(), `"state":"ACCEPTED"`) {
		t.Fatalf("status=%d calls=%d/%d body=%s", recorder.Code, calls.statusCount, calls.saveCount, recorder.Body.String())
	}
}

func TestPermissionAuthoringStatusKeepsAcceptedCommandAfterReplayError(t *testing.T) {
	for _, category := range []commonsemantic.FailureCategory{
		commonsemantic.FailureStaleState,
		commonsemantic.FailureMissing,
		commonsemantic.FailureForbidden,
	} {
		t.Run(string(category), func(t *testing.T) {
			service, calls := permissionAuthoringHTTPTestService(t)
			calls.statusAcceptedCount = 2
			calls.saveErr = &commonsemantic.Failure{Category: category}
			token, err := permissionauthoringsemantic.NewAuthoringToken("permission-set-1", 8)
			if err != nil {
				t.Fatal(err)
			}
			body := fmt.Sprintf(`{"commandId":"permission-authoring:accepted-error","target":{"type":"permissionSet","id":"permission-set-1"},"expectedAuthoringToken":%q,"minCatalogRevision":"18446744073709551615","changes":{"system":[{"capabilityId":"ViewSetup","enabled":true}]}}`, token)
			recorder := httptest.NewRecorder()
			service.ServeHTTP(recorder, permissionAuthoringHTTPRequest(PermissionAuthoringStatusPath, `{"command":`+body+`}`))
			if recorder.Code != http.StatusOK || calls.statusCount != 2 || calls.saveCount != 1 ||
				!strings.Contains(recorder.Body.String(), `"state":"ACCEPTED"`) {
				t.Fatalf("status=%d calls=%d/%d body=%s", recorder.Code, calls.statusCount, calls.saveCount, recorder.Body.String())
			}
		})
	}
}

func TestPermissionAuthoringSaveReconcilesAmbiguityUnderOneBearer(t *testing.T) {
	service, calls := permissionAuthoringHTTPTestService(t)
	calls.saveErr = &commonsemantic.Failure{Category: commonsemantic.FailureDeadlineExceeded}
	token, err := permissionauthoringsemantic.NewAuthoringToken("permission-set-1", 8)
	if err != nil {
		t.Fatal(err)
	}
	recorder := httptest.NewRecorder()
	service.ServeHTTP(recorder, permissionAuthoringHTTPRequest(PermissionAuthoringSavePath,
		fmt.Sprintf(`{"commandId":"command-1","target":{"type":"permissionSet","id":"permission-set-1"},"expectedAuthoringToken":%q,"minCatalogRevision":"18446744073709551615","changes":{"system":[{"capabilityId":"ViewSetup","enabled":true}]}}`, token)))
	if recorder.Code != http.StatusOK || calls.saveCount != 1 || calls.statusCount != 1 ||
		calls.saveBearer != "user-secret" || calls.statusBearer != "user-secret" ||
		calls.status.CommandID != calls.save.CommandID {
		t.Fatalf("reconciled Save status=%d calls=%d/%d bearers=%q/%q body=%s", recorder.Code, calls.saveCount, calls.statusCount, calls.saveBearer, calls.statusBearer, recorder.Body.String())
	}
}

func TestPermissionAuthoringSaveReconcilesPostAdmissionResourceLimit(t *testing.T) {
	service, calls := permissionAuthoringHTTPTestService(t)
	calls.saveErr = &commonsemantic.Failure{Category: commonsemantic.FailureResourceExhausted, LimitKind: commonsemantic.LimitOperationCount}
	token, err := permissionauthoringsemantic.NewAuthoringToken("permission-set-1", 8)
	if err != nil {
		t.Fatal(err)
	}
	recorder := httptest.NewRecorder()
	service.ServeHTTP(recorder, permissionAuthoringHTTPRequest(PermissionAuthoringSavePath,
		fmt.Sprintf(`{"commandId":"command-1","target":{"type":"permissionSet","id":"permission-set-1"},"expectedAuthoringToken":%q,"minCatalogRevision":"18446744073709551615","changes":{"system":[{"capabilityId":"ViewSetup","enabled":true}]}}`, token)))
	if recorder.Code != http.StatusOK || calls.saveCount != 1 || calls.statusCount != 1 {
		t.Fatalf("resource-limited Save status=%d calls=%d/%d body=%s", recorder.Code, calls.saveCount, calls.statusCount, recorder.Body.String())
	}
}

func TestPermissionAuthoringSaveReplaysMissingCommandUnderCapturedBearer(t *testing.T) {
	service, calls := permissionAuthoringHTTPTestService(t)
	calls.saveErr = &commonsemantic.Failure{Category: commonsemantic.FailureDeadlineExceeded}
	calls.statusErr = &commonsemantic.Failure{Category: commonsemantic.FailureMissing}
	token, err := permissionauthoringsemantic.NewAuthoringToken("permission-set-1", 8)
	if err != nil {
		t.Fatal(err)
	}
	recorder := httptest.NewRecorder()
	service.ServeHTTP(recorder, permissionAuthoringHTTPRequest(PermissionAuthoringSavePath,
		fmt.Sprintf(`{"commandId":"command-1","target":{"type":"permissionSet","id":"permission-set-1"},"expectedAuthoringToken":%q,"minCatalogRevision":"18446744073709551615","changes":{"system":[{"capabilityId":"ViewSetup","enabled":true}]}}`, token)))
	if recorder.Code != http.StatusOK || calls.saveCount != 2 || calls.statusCount != 1 ||
		calls.saveBearer != "user-secret" || calls.statusBearer != "user-secret" ||
		calls.status.CommandID != calls.save.CommandID {
		t.Fatalf("missing-command reconciliation status=%d calls=%d/%d bearers=%q/%q body=%s", recorder.Code, calls.saveCount, calls.statusCount, calls.saveBearer, calls.statusBearer, recorder.Body.String())
	}
}

func TestPermissionAuthoringSavePreservesUnknownWhenStatusIsUnavailable(t *testing.T) {
	service, calls := permissionAuthoringHTTPTestService(t)
	calls.saveErr = &commonsemantic.Failure{Category: commonsemantic.FailureDeadlineExceeded}
	calls.statusErr = &commonsemantic.Failure{Category: commonsemantic.FailureUnavailable}
	token, err := permissionauthoringsemantic.NewAuthoringToken("permission-set-1", 8)
	if err != nil {
		t.Fatal(err)
	}
	recorder := httptest.NewRecorder()
	service.ServeHTTP(recorder, permissionAuthoringHTTPRequest(PermissionAuthoringSavePath,
		fmt.Sprintf(`{"commandId":"command-1","target":{"type":"permissionSet","id":"permission-set-1"},"expectedAuthoringToken":%q,"minCatalogRevision":"18446744073709551615","changes":{"system":[{"capabilityId":"ViewSetup","enabled":true}]}}`, token)))
	if recorder.Code != http.StatusServiceUnavailable || !strings.Contains(recorder.Body.String(), permissionAuthoringOutcomeUnknownCode) ||
		calls.saveCount != 1 || calls.statusCount != 1 {
		t.Fatalf("unknown Save status=%d calls=%d/%d body=%s", recorder.Code, calls.saveCount, calls.statusCount, recorder.Body.String())
	}
}

func TestPermissionAuthoringSnapshotProjectsEveryEmptyCollectionAsJSONArray(t *testing.T) {
	service, calls := permissionAuthoringHTTPTestService(t)
	calls.emptySnapshot = true
	recorder := httptest.NewRecorder()
	service.ServeHTTP(recorder, permissionAuthoringHTTPRequest(PermissionAuthoringSnapshotPath, `{"target":{"type":"permissionSet","id":"permission-set-1"}}`))
	if recorder.Code != http.StatusOK {
		t.Fatalf("Snapshot status=%d body=%s", recorder.Code, recorder.Body.String())
	}
	var body struct {
		Catalog map[string]json.RawMessage `json:"catalog"`
		Grants  map[string]json.RawMessage `json:"grants"`
	}
	if err := json.Unmarshal(recorder.Body.Bytes(), &body); err != nil {
		t.Fatal(err)
	}
	for _, family := range []string{"system", "recordTypes", "custom"} {
		if got := string(body.Catalog[family]); got != "[]" {
			t.Fatalf("catalog.%s = %s, want [] (body=%s)", family, got, recorder.Body.String())
		}
	}
	for _, family := range []string{"system", "objects", "fields", "recordTypes", "custom"} {
		if got := string(body.Grants[family]); got != "[]" {
			t.Fatalf("grants.%s = %s, want [] (body=%s)", family, got, recorder.Body.String())
		}
	}
}

func TestPermissionAuthoringFieldCatalogUsesCatalogNotCallerFLS(t *testing.T) {
	service, calls := permissionAuthoringHTTPTestService(t)
	standardObject := "standard_object"
	view := searchTestView(t, []searchObjectSpec{{
		APIName: "Account", Label: "Account", TableType: &standardObject, Fields: []searchFieldSpec{
			{APIName: "Name", Label: "Account Name", Type: "string"},
			// A caller-facing Describe is allowed to omit this field when the
			// operator's own FLS denies CanRead. Permission authoring is instead
			// authorized by the successful Runtime Snapshot below.
			{APIName: "Secret__c", Label: "Secret", Type: "string"},
		},
	}})
	service.appMetadataV3 = func(_ context.Context, request catalogsemantic.GetRequest) (catalogsemantic.AppMetadataViewV3, error) {
		if request.MinCatalogRevision == nil || *request.MinCatalogRevision != view.Receipts.CatalogRevision {
			t.Fatalf("AppMetadata minimum revision = %v, want %d", request.MinCatalogRevision, view.Receipts.CatalogRevision)
		}
		return view, nil
	}
	service.permissionAuthoring.readSnapshot = func(_ context.Context, bearer string, request permissionauthoringsemantic.SnapshotRequest) (permissionauthoringsemantic.SnapshotResponse, error) {
		calls.snapshotBearer, calls.snapshot = bearer, request
		calls.snapshotCount++
		token, err := permissionauthoringsemantic.NewAuthoringToken("permission-set-1", 8)
		if err != nil {
			t.Fatal(err)
		}
		return permissionauthoringsemantic.NormalizeSnapshotResponse(permissionauthoringsemantic.SnapshotResponse{
			CanonicalPermissionSetID: "permission-set-1",
			AuthoringToken:           token,
			Receipts:                 permissionAuthoringReceipts(view.Receipts.CatalogRevision),
		}), nil
	}

	recorder := httptest.NewRecorder()
	service.ServeHTTP(recorder, permissionAuthoringHTTPRequest(
		"/services/data/v63.0/permissions/authoring/field-catalog",
		`{"target":{"type":"profile","id":"profile-1"},"resourceType":"Account","minCatalogRevision":"17"}`,
	))
	if recorder.Code != http.StatusOK {
		t.Fatalf("field catalog status=%d body=%s", recorder.Code, recorder.Body.String())
	}
	var body struct {
		ResourceType    string `json:"resourceType"`
		CatalogRevision string `json:"catalogRevision"`
		Fields          []struct {
			Name  string `json:"name"`
			Label string `json:"label"`
		} `json:"fields"`
	}
	if err := json.Unmarshal(recorder.Body.Bytes(), &body); err != nil {
		t.Fatal(err)
	}
	if calls.snapshotCount != 1 || calls.snapshot.Target.Kind != permissionauthoringsemantic.TargetProfile ||
		calls.snapshot.Target.ID != "profile-1" || calls.snapshotBearer != "user-secret" {
		t.Fatalf("authoring authorization calls=%d bearer=%q target=%+v", calls.snapshotCount, calls.snapshotBearer, calls.snapshot.Target)
	}
	if body.ResourceType != "Account" || body.CatalogRevision != "17" || len(body.Fields) != 2 ||
		body.Fields[0].Name != "Name" || body.Fields[1].Name != "Secret__c" {
		t.Fatalf("field catalog=%+v body=%s", body, recorder.Body.String())
	}
}

func TestPermissionAuthoringFieldCatalogFailsClosedBeforeCatalogRead(t *testing.T) {
	service, calls := permissionAuthoringHTTPTestService(t)
	calls.snapshotErr = &commonsemantic.Failure{Category: commonsemantic.FailureForbidden}
	catalogReads := 0
	service.appMetadataV3 = func(context.Context, catalogsemantic.GetRequest) (catalogsemantic.AppMetadataViewV3, error) {
		catalogReads++
		return catalogsemantic.AppMetadataViewV3{}, nil
	}

	recorder := httptest.NewRecorder()
	service.ServeHTTP(recorder, permissionAuthoringHTTPRequest(
		PermissionAuthoringFieldCatalogPath,
		`{"target":{"type":"permissionSet","id":"permission-set-1"},"resourceType":"Account","minCatalogRevision":"17"}`,
	))
	if recorder.Code != http.StatusForbidden || calls.snapshotCount != 1 || catalogReads != 0 {
		t.Fatalf("status=%d snapshotCalls=%d catalogReads=%d body=%s", recorder.Code, calls.snapshotCount, catalogReads, recorder.Body.String())
	}
}

func TestLegacySystemPermissionPatchDelegatesToOneDeterministicRuntimeCommand(t *testing.T) {
	service, calls := permissionAuthoringHTTPTestService(t)
	calls.snapshotSystemEnabled = false
	path := LegacyPermissionSetSystemGrantsPrefix + "permission-set-1"
	var firstCommandID string
	for attempt := 0; attempt < 2; attempt++ {
		request := permissionAuthoringHTTPRequest(path, `{"grants":{"ViewSetup":true}}`)
		// The compatibility envelope retains its historical PATCH method while
		// Runtime remains the only mutation owner.
		request.Method = http.MethodPatch
		recorder := httptest.NewRecorder()
		service.ServeHTTP(recorder, request)
		if recorder.Code != http.StatusOK || recorder.Body.String() != "{\"success\":true}" {
			t.Fatalf("legacy PATCH status=%d body=%s", recorder.Code, recorder.Body.String())
		}
		if calls.snapshot.Target.Kind != permissionauthoringsemantic.TargetPermissionSet || calls.snapshot.Target.ID != "permission-set-1" ||
			len(calls.save.Changes.System) != 1 || calls.save.Changes.System[0].CapabilityID != "ViewSetup" || !calls.save.Changes.System[0].Enabled {
			t.Fatalf("snapshot=%+v save=%+v", calls.snapshot, calls.save)
		}
		if attempt == 0 {
			firstCommandID = calls.save.CommandID
		} else if calls.save.CommandID != firstCommandID {
			t.Fatalf("legacy retry command ID = %q, want %q", calls.save.CommandID, firstCommandID)
		}
	}
	if calls.saveCount != 2 || calls.statusCount != 0 {
		t.Fatalf("save calls=%d status calls=%d", calls.saveCount, calls.statusCount)
	}
}

func TestLegacySystemPermissionNoopStillRequiresRuntimeSnapshotAuthorization(t *testing.T) {
	service, calls := permissionAuthoringHTTPTestService(t)
	calls.snapshotErr = &commonsemantic.Failure{Category: commonsemantic.FailureForbidden}
	request := permissionAuthoringHTTPRequest(LegacyPermissionSetSystemGrantsPrefix+"permission-set-1", `{"grants":{"ViewSetup":true}}`)
	request.Method = http.MethodPatch
	recorder := httptest.NewRecorder()
	service.ServeHTTP(recorder, request)
	if recorder.Code != http.StatusForbidden || calls.snapshotCount != 1 || calls.saveCount != 0 {
		t.Fatalf("unauthorized no-op status=%d snapshot=%d save=%d body=%s", recorder.Code, calls.snapshotCount, calls.saveCount, recorder.Body.String())
	}
}

func TestLegacySystemPermissionPatchReconcilesEveryAmbiguousSaveWithExactCommand(t *testing.T) {
	for _, failure := range []*commonsemantic.Failure{
		{Category: commonsemantic.FailureUnavailable},
		{Category: commonsemantic.FailureIncompatible},
		{Category: commonsemantic.FailureResourceExhausted, LimitKind: commonsemantic.LimitOperationCount},
	} {
		t.Run(string(failure.Category)+"/"+string(failure.LimitKind), func(t *testing.T) {
			service, calls := permissionAuthoringHTTPTestService(t)
			calls.snapshotSystemEnabled = false
			calls.saveErr = failure
			request := permissionAuthoringHTTPRequest(LegacyPermissionSetSystemGrantsPrefix+"permission-set-1", `{"grants":{"ViewSetup":true}}`)
			request.Method = http.MethodPatch
			recorder := httptest.NewRecorder()
			service.ServeHTTP(recorder, request)
			if recorder.Code != http.StatusOK || calls.saveCount != 1 || calls.statusCount != 1 || calls.status.CommandID != calls.save.CommandID {
				t.Fatalf("status=%d save=%+v statusRequest=%+v calls=%d/%d body=%s", recorder.Code, calls.save, calls.status, calls.saveCount, calls.statusCount, recorder.Body.String())
			}
		})
	}
}

func TestLegacySystemPermissionPatchPreservesUnknownOutcomeAfterReplayRejection(t *testing.T) {
	service, calls := permissionAuthoringHTTPTestService(t)
	calls.snapshotSystemEnabled = false
	calls.saveErr = &commonsemantic.Failure{Category: commonsemantic.FailureDeadlineExceeded}
	calls.statusErr = &commonsemantic.Failure{Category: commonsemantic.FailureMissing}
	calls.replayRejected = true
	request := permissionAuthoringHTTPRequest(LegacyPermissionSetSystemGrantsPrefix+"permission-set-1", `{"grants":{"ViewSetup":true}}`)
	request.Method = http.MethodPatch
	recorder := httptest.NewRecorder()
	service.ServeHTTP(recorder, request)
	if recorder.Code != http.StatusServiceUnavailable || !strings.Contains(recorder.Body.String(), permissionAuthoringOutcomeUnknownCode) ||
		calls.saveCount != 2 || calls.statusCount != 1 {
		t.Fatalf("status=%d calls=%d/%d body=%s", recorder.Code, calls.saveCount, calls.statusCount, recorder.Body.String())
	}
}

func TestLegacySystemPermissionPatchReservesStatusBudgetAfterSaveDeadline(t *testing.T) {
	service, calls := permissionAuthoringHTTPTestService(t)
	service.requestTimeout = 60 * time.Millisecond
	calls.snapshotSystemEnabled = false
	calls.saveWaitForContext = true
	request := permissionAuthoringHTTPRequest(LegacyPermissionSetSystemGrantsPrefix+"permission-set-1", `{"grants":{"ViewSetup":true}}`)
	request.Method = http.MethodPatch
	recorder := httptest.NewRecorder()
	service.ServeHTTP(recorder, request)
	if recorder.Code != http.StatusOK || calls.saveCount != 1 || calls.statusCount != 1 || calls.statusContextErr != nil || calls.status.CommandID != calls.save.CommandID {
		t.Fatalf("status=%d save=%+v statusRequest=%+v statusContextErr=%v calls=%d/%d body=%s", recorder.Code, calls.save, calls.status, calls.statusContextErr, calls.saveCount, calls.statusCount, recorder.Body.String())
	}
}

func TestPermissionAuthoringConstructionRejectsPartialLifecycle(t *testing.T) {
	_, err := NewRuntimePermissionAuthoringClient(
		func(context.Context, string, permissionauthoringsemantic.SnapshotRequest) (permissionauthoringsemantic.SnapshotResponse, error) {
			return permissionauthoringsemantic.SnapshotResponse{}, nil
		}, nil, nil,
	)
	if err == nil {
		t.Fatal("partial Permission Authoring lifecycle was accepted")
	}
}
