package mapping

import (
	"context"

	commonsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/commonv1"
	semantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/permissionauthoringv1"
	"github.com/pingcap-inc/nexuscrm-contract/wire-go/envelope"
	runtimev1 "github.com/pingcap-inc/nexuscrm-contract/wire-go/gen/runtime/v1"
	"google.golang.org/protobuf/proto"
)

const supportedPermissionAuthoringSemanticMappingRevision uint32 = 3

type permissionAuthoringSemanticMappingRevisioner interface {
	PermissionAuthoringSemanticMappingRevision() uint32
}

func ToWireReadPermissionAuthoringSnapshotRequest(ctx context.Context, request semantic.SnapshotRequest) (*runtimev1.ReadPermissionAuthoringSnapshotRequest, error) {
	if err := requirePermissionAuthoringMapping(request); err != nil {
		return nil, err
	}
	if err := semantic.ValidateSnapshotRequest(ctx, request); err != nil {
		return nil, err
	}
	return &runtimev1.ReadPermissionAuthoringSnapshotRequest{Target: toWirePermissionAuthoringTarget(request.Target), MinCatalogRevision: request.MinCatalogRevision}, nil
}

func FromWireReadPermissionAuthoringSnapshotRequest(ctx context.Context, request *runtimev1.ReadPermissionAuthoringSnapshotRequest) (semantic.SnapshotRequest, error) {
	if request == nil || request.GetTarget() == nil {
		return semantic.SnapshotRequest{}, invalidPlatformWire()
	}
	target, ok := fromWirePermissionAuthoringTarget(request.GetTarget())
	if !ok {
		return semantic.SnapshotRequest{}, invalidPlatformWire()
	}
	if err := commonsemantic.ValidateRequestContext(ctx); err != nil {
		return semantic.SnapshotRequest{}, err
	}
	if err := preflightPermissionAuthoringRequest(request, request.GetTarget().GetId()); err != nil {
		return semantic.SnapshotRequest{}, err
	}
	result := semantic.SnapshotRequest{Target: target, MinCatalogRevision: request.MinCatalogRevision}
	if err := requirePermissionAuthoringMapping(result); err != nil {
		return semantic.SnapshotRequest{}, err
	}
	if err := semantic.ValidateSnapshotRequest(ctx, result); err != nil {
		return semantic.SnapshotRequest{}, err
	}
	return result, nil
}

func ToWireReadPermissionAuthoringSnapshotResponse(request semantic.SnapshotRequest, response semantic.SnapshotResponse) (*runtimev1.ReadPermissionAuthoringSnapshotResponse, error) {
	if err := requirePermissionAuthoringMapping(request, response); err != nil {
		return nil, err
	}
	response = semantic.NormalizeSnapshotResponse(response)
	if err := semantic.ValidateSnapshotResponse(request, response); err != nil {
		return nil, err
	}
	result := &runtimev1.ReadPermissionAuthoringSnapshotResponse{
		CanonicalPermissionSetId: response.CanonicalPermissionSetID,
		AuthoringToken:           response.AuthoringToken,
		Catalog:                  toWirePermissionAuthoringCatalog(response.Catalog),
		Grants:                   toWirePermissionAuthoringStoredGrants(response.Grants),
		Receipts:                 toWireReceipts(response.Receipts, platformCapability(semantic.CapabilityName)),
	}
	if proto.Size(result) > envelope.MaxResponseWireBytes {
		return nil, internalPlatformWire()
	}
	return result, nil
}

func FromWireReadPermissionAuthoringSnapshotResponse(request semantic.SnapshotRequest, response *runtimev1.ReadPermissionAuthoringSnapshotResponse) (semantic.SnapshotResponse, error) {
	if err := requirePermissionAuthoringMapping(request); err != nil {
		return semantic.SnapshotResponse{}, err
	}
	if response == nil || response.GetReceipts() == nil {
		return semantic.SnapshotResponse{}, incompatibleFailureFor(platformCapability(semantic.CapabilityName))
	}
	receipts, err := fromWireReceipts(response.GetReceipts(), platformCapability(semantic.CapabilityName))
	if err != nil {
		return semantic.SnapshotResponse{}, err
	}
	if response.GetCatalog() == nil || response.GetGrants() == nil {
		return semantic.SnapshotResponse{}, internalPlatformWire()
	}
	if err := preflightPermissionAuthoringSnapshotResponse(response); err != nil {
		return semantic.SnapshotResponse{}, err
	}
	catalog, ok := fromWirePermissionAuthoringCatalog(response.GetCatalog())
	if !ok {
		return semantic.SnapshotResponse{}, internalPlatformWire()
	}
	grants, ok := fromWirePermissionAuthoringStoredGrants(response.GetGrants())
	if !ok {
		return semantic.SnapshotResponse{}, internalPlatformWire()
	}
	result := semantic.SnapshotResponse{CanonicalPermissionSetID: response.GetCanonicalPermissionSetId(), AuthoringToken: response.GetAuthoringToken(), Catalog: catalog, Grants: grants, Receipts: receipts}
	if err := requirePermissionAuthoringMapping(result); err != nil {
		return semantic.SnapshotResponse{}, err
	}
	if err := semantic.ValidateSnapshotResponse(request, result); err != nil {
		return semantic.SnapshotResponse{}, internalPlatformWire()
	}
	return result, nil
}

func ToWireSavePermissionAuthoringRequest(ctx context.Context, request semantic.Request) (*runtimev1.SavePermissionAuthoringRequest, error) {
	if err := requirePermissionAuthoringMapping(request); err != nil {
		return nil, err
	}
	if err := semantic.ValidateRequest(ctx, request); err != nil {
		return nil, err
	}
	request = semantic.NormalizeRequest(request)
	result := &runtimev1.SavePermissionAuthoringRequest{
		CommandId: request.CommandID, Target: toWirePermissionAuthoringTarget(request.Target),
		ExpectedAuthoringToken: request.ExpectedAuthoringToken, Changes: toWirePermissionAuthoringChanges(request.Changes),
		MinCatalogRevision: request.MinCatalogRevision,
	}
	if proto.Size(result) > envelope.MaxRequestWireBytes {
		return nil, platformLimitFailure(commonsemantic.LimitWireFrame, envelope.MaxRequestWireBytes)
	}
	return result, nil
}

func FromWireSavePermissionAuthoringRequest(ctx context.Context, request *runtimev1.SavePermissionAuthoringRequest) (semantic.Request, error) {
	if request == nil || request.GetTarget() == nil || request.GetChanges() == nil {
		return semantic.Request{}, invalidPlatformWire()
	}
	target, ok := fromWirePermissionAuthoringTarget(request.GetTarget())
	if !ok {
		return semantic.Request{}, invalidPlatformWire()
	}
	if err := commonsemantic.ValidateRequestContext(ctx); err != nil {
		return semantic.Request{}, err
	}
	if err := preflightPermissionAuthoringSaveRequest(request); err != nil {
		return semantic.Request{}, err
	}
	changes, ok := fromWirePermissionAuthoringChanges(request.GetChanges())
	if !ok {
		return semantic.Request{}, invalidPlatformWire()
	}
	result := semantic.Request{CommandID: request.GetCommandId(), Target: target, ExpectedAuthoringToken: request.GetExpectedAuthoringToken(), Changes: changes, MinCatalogRevision: request.MinCatalogRevision}
	if err := requirePermissionAuthoringMapping(result); err != nil {
		return semantic.Request{}, err
	}
	if err := semantic.ValidateRequest(ctx, result); err != nil {
		return semantic.Request{}, err
	}
	return result, nil
}

func ToWireSavePermissionAuthoringResponse(request semantic.Request, response semantic.Response) (*runtimev1.SavePermissionAuthoringResponse, error) {
	if err := requirePermissionAuthoringMapping(request, response); err != nil {
		return nil, err
	}
	if err := semantic.ValidateResponse(request, response); err != nil {
		return nil, err
	}
	return toWirePermissionAuthoringTerminal(response)
}

func FromWireSavePermissionAuthoringResponse(request semantic.Request, response *runtimev1.SavePermissionAuthoringResponse) (semantic.Response, error) {
	if err := requirePermissionAuthoringMapping(request); err != nil {
		return semantic.Response{}, err
	}
	result, err := fromWirePermissionAuthoringTerminal(response)
	if err != nil {
		return semantic.Response{}, err
	}
	if err := requirePermissionAuthoringMapping(result); err != nil {
		return semantic.Response{}, err
	}
	if err := semantic.ValidateResponse(request, result); err != nil {
		return semantic.Response{}, err
	}
	return result, nil
}

func ToWireGetPermissionAuthoringStatusRequest(ctx context.Context, request semantic.StatusRequest) (*runtimev1.GetPermissionAuthoringStatusRequest, error) {
	if err := requirePermissionAuthoringMapping(request); err != nil {
		return nil, err
	}
	if err := semantic.ValidateStatusRequest(ctx, request); err != nil {
		return nil, err
	}
	digest, err := digestToWire(request.CommandDigest)
	if err != nil {
		return nil, invalidPlatformWire()
	}
	return &runtimev1.GetPermissionAuthoringStatusRequest{CommandId: request.CommandID, SemanticSha256: digest}, nil
}

func FromWireGetPermissionAuthoringStatusRequest(ctx context.Context, request *runtimev1.GetPermissionAuthoringStatusRequest) (semantic.StatusRequest, error) {
	if request == nil {
		return semantic.StatusRequest{}, invalidPlatformWire()
	}
	if err := commonsemantic.ValidateRequestContext(ctx); err != nil {
		return semantic.StatusRequest{}, err
	}
	if err := preflightPermissionAuthoringRequest(request, request.GetCommandId()); err != nil {
		return semantic.StatusRequest{}, err
	}
	digest, err := digestFromWire(request.GetSemanticSha256())
	if err != nil {
		return semantic.StatusRequest{}, err
	}
	result := semantic.StatusRequest{CommandID: request.GetCommandId(), CommandDigest: digest}
	if err := requirePermissionAuthoringMapping(result); err != nil {
		return semantic.StatusRequest{}, err
	}
	if err := semantic.ValidateStatusRequest(ctx, result); err != nil {
		return semantic.StatusRequest{}, err
	}
	return result, nil
}

func ToWireGetPermissionAuthoringStatusResponse(request semantic.StatusRequest, response semantic.StatusResponse) (*runtimev1.GetPermissionAuthoringStatusResponse, error) {
	if err := requirePermissionAuthoringMapping(request, response); err != nil {
		return nil, err
	}
	if err := semantic.ValidateStatusResponse(request, response); err != nil {
		return nil, err
	}
	digest, err := digestToWire(response.CommandDigest)
	if err != nil {
		return nil, internalPlatformWire()
	}
	result := &runtimev1.GetPermissionAuthoringStatusResponse{CommandId: response.CommandID, SemanticSha256: digest, State: toWirePermissionAuthoringCommandState(response.State)}
	if response.Result != nil {
		result.Result, err = toWirePermissionAuthoringTerminal(*response.Result)
		if err != nil {
			return nil, err
		}
	}
	if proto.Size(result) > envelope.MaxResponseWireBytes {
		return nil, internalPlatformWire()
	}
	return result, nil
}

// ToWireGetPermissionAuthoringStatusResponseForRequest binds a completed
// reconciliation result to the original Save intent before it crosses the
// wire. The Status RPC itself carries only command identity, so the
// request-independent mapper above remains available to status-only callers.
func ToWireGetPermissionAuthoringStatusResponseForRequest(request semantic.Request, response semantic.StatusResponse) (*runtimev1.GetPermissionAuthoringStatusResponse, error) {
	if err := requirePermissionAuthoringMapping(request, response); err != nil {
		return nil, err
	}
	if err := semantic.ValidateStatusResponseForRequest(request, response); err != nil {
		return nil, err
	}
	statusRequest, err := semantic.StatusRequestFor(request)
	if err != nil {
		return nil, err
	}
	return ToWireGetPermissionAuthoringStatusResponse(statusRequest, response)
}

func FromWireGetPermissionAuthoringStatusResponse(request semantic.StatusRequest, response *runtimev1.GetPermissionAuthoringStatusResponse) (semantic.StatusResponse, error) {
	if err := requirePermissionAuthoringMapping(request); err != nil {
		return semantic.StatusResponse{}, err
	}
	if response == nil {
		return semantic.StatusResponse{}, incompatibleFailureFor(platformCapability(semantic.CapabilityName))
	}
	commandState, ok := fromWirePermissionAuthoringCommandState(response.GetState())
	if !ok || (commandState == semantic.CommandCompleted) != (response.GetResult() != nil) {
		return semantic.StatusResponse{}, internalPlatformWire()
	}
	var terminalReceipts semantic.Receipts
	if response.GetResult() != nil {
		var err error
		terminalReceipts, err = fromWirePermissionAuthoringTerminalReceipts(response.GetResult())
		if err != nil {
			return semantic.StatusResponse{}, err
		}
	}
	if proto.Size(response) > envelope.MaxResponseWireBytes {
		return semantic.StatusResponse{}, internalPlatformWire()
	}
	digest, err := digestFromWire(response.GetSemanticSha256())
	if err != nil {
		return semantic.StatusResponse{}, internalPlatformWire()
	}
	result := semantic.StatusResponse{CommandID: response.GetCommandId(), CommandDigest: digest, State: commandState}
	if response.GetResult() != nil {
		terminal, err := fromWirePermissionAuthoringTerminalPayload(response.GetResult(), terminalReceipts)
		if err != nil {
			return semantic.StatusResponse{}, err
		}
		result.Result = &terminal
	}
	if err := requirePermissionAuthoringMapping(result); err != nil {
		return semantic.StatusResponse{}, err
	}
	if err := semantic.ValidateStatusResponse(request, result); err != nil {
		return semantic.StatusResponse{}, err
	}
	return result, nil
}

// FromWireGetPermissionAuthoringStatusResponseForRequest rejects a terminal
// result that is well formed in isolation but does not represent the exact
// transition from the caller's original Save baseline.
func FromWireGetPermissionAuthoringStatusResponseForRequest(request semantic.Request, response *runtimev1.GetPermissionAuthoringStatusResponse) (semantic.StatusResponse, error) {
	if err := requirePermissionAuthoringMapping(request); err != nil {
		return semantic.StatusResponse{}, err
	}
	statusRequest, err := semantic.StatusRequestFor(request)
	if err != nil {
		return semantic.StatusResponse{}, err
	}
	result, err := FromWireGetPermissionAuthoringStatusResponse(statusRequest, response)
	if err != nil {
		return semantic.StatusResponse{}, err
	}
	if err := semantic.ValidateStatusResponseForRequest(request, result); err != nil {
		return semantic.StatusResponse{}, err
	}
	return result, nil
}

func toWirePermissionAuthoringTerminal(response semantic.Response) (*runtimev1.SavePermissionAuthoringResponse, error) {
	digest, err := digestToWire(response.CommandDigest)
	if err != nil {
		return nil, internalPlatformWire()
	}
	return &runtimev1.SavePermissionAuthoringResponse{
		CommandId: response.CommandID, SemanticSha256: digest, Outcome: toWirePermissionAuthoringOutcome(response.Outcome),
		RejectionCode: toWirePermissionAuthoringRejection(response.RejectionCode), CanonicalPermissionSetId: response.CanonicalPermissionSetID,
		AuthoringToken: response.AuthoringToken, Receipts: toWireReceipts(response.Receipts, platformCapability(semantic.CapabilityName)), OutcomeExpiresAtUtc: response.OutcomeExpiresAtUTC,
	}, nil
}

func fromWirePermissionAuthoringTerminal(response *runtimev1.SavePermissionAuthoringResponse) (semantic.Response, error) {
	receipts, err := fromWirePermissionAuthoringTerminalReceipts(response)
	if err != nil {
		return semantic.Response{}, err
	}
	if proto.Size(response) > envelope.MaxResponseWireBytes {
		return semantic.Response{}, internalPlatformWire()
	}
	return fromWirePermissionAuthoringTerminalPayload(response, receipts)
}

func fromWirePermissionAuthoringTerminalReceipts(response *runtimev1.SavePermissionAuthoringResponse) (semantic.Receipts, error) {
	if response == nil || response.GetReceipts() == nil {
		return semantic.Receipts{}, incompatibleFailureFor(platformCapability(semantic.CapabilityName))
	}
	return fromWireReceipts(response.GetReceipts(), platformCapability(semantic.CapabilityName))
}

func fromWirePermissionAuthoringTerminalPayload(response *runtimev1.SavePermissionAuthoringResponse, receipts semantic.Receipts) (semantic.Response, error) {
	digest, err := digestFromWire(response.GetSemanticSha256())
	if err != nil {
		return semantic.Response{}, internalPlatformWire()
	}
	outcome, ok := fromWirePermissionAuthoringOutcome(response.GetOutcome())
	if !ok {
		return semantic.Response{}, internalPlatformWire()
	}
	rejectionCode, ok := fromWirePermissionAuthoringRejection(response.GetRejectionCode())
	if !ok {
		return semantic.Response{}, internalPlatformWire()
	}
	return semantic.Response{CommandID: response.GetCommandId(), CommandDigest: digest, Outcome: outcome, RejectionCode: rejectionCode, CanonicalPermissionSetID: response.GetCanonicalPermissionSetId(), AuthoringToken: response.GetAuthoringToken(), Receipts: receipts, OutcomeExpiresAtUTC: response.GetOutcomeExpiresAtUtc()}, nil
}

func preflightPermissionAuthoringRequest(message proto.Message, values ...string) error {
	budget := newWireStringBudget(semantic.MaxSemanticRequestBytes)
	if !budget.take(values...) {
		return platformLimitFailure(commonsemantic.LimitSemanticRequest, semantic.MaxSemanticRequestBytes)
	}
	if proto.Size(message) > envelope.MaxRequestWireBytes {
		return platformLimitFailure(commonsemantic.LimitWireFrame, envelope.MaxRequestWireBytes)
	}
	return nil
}

func preflightPermissionAuthoringSaveRequest(request *runtimev1.SavePermissionAuthoringRequest) error {
	changes := request.GetChanges()
	switch {
	case len(changes.GetSystem()) > semantic.MaxSystemChanges:
		return platformLimitFailure(commonsemantic.LimitOperationCount, semantic.MaxSystemChanges)
	case len(changes.GetCustom()) > semantic.MaxCustomChanges:
		return platformLimitFailure(commonsemantic.LimitOperationCount, semantic.MaxCustomChanges)
	case len(changes.GetObjects()) > semantic.MaxObjectChanges:
		return platformLimitFailure(commonsemantic.LimitOperationCount, semantic.MaxObjectChanges)
	case len(changes.GetRecordTypes()) > semantic.MaxRecordTypeChanges:
		return platformLimitFailure(commonsemantic.LimitOperationCount, semantic.MaxRecordTypeChanges)
	case len(changes.GetFields()) > semantic.MaxFieldChanges:
		return platformLimitFailure(commonsemantic.LimitFieldCount, semantic.MaxFieldChanges)
	}
	values := []string{request.GetCommandId(), request.GetTarget().GetId(), request.GetExpectedAuthoringToken()}
	for _, value := range changes.GetSystem() {
		if value == nil {
			return invalidPlatformWire()
		}
		values = append(values, value.GetCapabilityId())
	}
	for _, value := range changes.GetObjects() {
		if value == nil {
			return invalidPlatformWire()
		}
		values = append(values, value.GetResourceType())
	}
	for _, value := range changes.GetFields() {
		if value == nil {
			return invalidPlatformWire()
		}
		values = append(values, value.GetResourceType(), value.GetFieldName())
	}
	for _, value := range changes.GetRecordTypes() {
		if value == nil {
			return invalidPlatformWire()
		}
		values = append(values, value.GetRecordTypeId(), value.GetResourceType())
	}
	for _, value := range changes.GetCustom() {
		if value == nil {
			return invalidPlatformWire()
		}
		values = append(values, value.GetCapabilityId())
	}
	return preflightPermissionAuthoringRequest(request, values...)
}

func preflightPermissionAuthoringSnapshotResponse(response *runtimev1.ReadPermissionAuthoringSnapshotResponse) error {
	catalog, grants := response.GetCatalog(), response.GetGrants()
	if len(catalog.GetSystem()) > semantic.MaxSystemChanges || len(catalog.GetRecordTypes()) > semantic.MaxRecordTypeChanges || len(catalog.GetCustom()) > semantic.MaxCustomChanges || len(grants.GetSystem()) > semantic.MaxSystemChanges || len(grants.GetObjects()) > semantic.MaxObjectChanges || len(grants.GetFields()) > semantic.MaxFieldChanges || len(grants.GetRecordTypes()) > semantic.MaxRecordTypeChanges || len(grants.GetCustom()) > semantic.MaxCustomChanges || proto.Size(response) > envelope.MaxResponseWireBytes {
		return internalPlatformWire()
	}
	return nil
}

func toWirePermissionAuthoringTarget(value semantic.Target) *runtimev1.PermissionAuthoringTarget {
	return &runtimev1.PermissionAuthoringTarget{Kind: toWirePermissionAuthoringTargetKind(value.Kind), Id: value.ID}
}
func fromWirePermissionAuthoringTarget(value *runtimev1.PermissionAuthoringTarget) (semantic.Target, bool) {
	kind, ok := fromWirePermissionAuthoringTargetKind(value.GetKind())
	if !ok {
		return semantic.Target{}, false
	}
	return semantic.Target{Kind: kind, ID: value.GetId()}, true
}

func toWirePermissionAuthoringCatalog(value semantic.SnapshotCatalog) *runtimev1.PermissionAuthoringCatalog {
	result := &runtimev1.PermissionAuthoringCatalog{}
	for _, v := range value.System {
		result.System = append(result.System, &runtimev1.PermissionAuthoringSystemPermission{PermissionId: v.PermissionID, Label: v.Label, Category: v.Category, Description: v.Description, RequiresPermissionId: v.RequiresPermissionID})
	}
	for _, v := range value.RecordTypes {
		result.RecordTypes = append(result.RecordTypes, &runtimev1.PermissionAuthoringRecordType{RecordTypeId: v.RecordTypeID, ResourceType: v.ResourceType, StableName: v.StableName, Label: v.Label, Active: v.Active})
	}
	for _, v := range value.Custom {
		result.Custom = append(result.Custom, &runtimev1.PermissionAuthoringCustomPermission{PermissionId: v.PermissionID, StableName: v.StableName, Label: v.Label})
	}
	return result
}

func fromWirePermissionAuthoringCatalog(value *runtimev1.PermissionAuthoringCatalog) (semantic.SnapshotCatalog, bool) {
	result := semantic.SnapshotCatalog{}
	for _, v := range value.GetSystem() {
		if v == nil {
			return semantic.SnapshotCatalog{}, false
		}
		result.System = append(result.System, semantic.SystemPermission{PermissionID: v.GetPermissionId(), Label: v.GetLabel(), Category: v.GetCategory(), Description: v.GetDescription(), RequiresPermissionID: v.GetRequiresPermissionId()})
	}
	for _, v := range value.GetRecordTypes() {
		if v == nil {
			return semantic.SnapshotCatalog{}, false
		}
		result.RecordTypes = append(result.RecordTypes, semantic.RecordType{RecordTypeID: v.GetRecordTypeId(), ResourceType: v.GetResourceType(), StableName: v.GetStableName(), Label: v.GetLabel(), Active: v.GetActive()})
	}
	for _, v := range value.GetCustom() {
		if v == nil {
			return semantic.SnapshotCatalog{}, false
		}
		result.Custom = append(result.Custom, semantic.CustomPermission{PermissionID: v.GetPermissionId(), StableName: v.GetStableName(), Label: v.GetLabel()})
	}
	return result, true
}

func toWirePermissionAuthoringStoredGrants(value semantic.StoredGrants) *runtimev1.PermissionAuthoringStoredGrants {
	result := &runtimev1.PermissionAuthoringStoredGrants{}
	for _, v := range value.System {
		result.System = append(result.System, &runtimev1.PermissionAuthoringCapabilityGrant{CapabilityId: v.CapabilityID, Enabled: v.Enabled})
	}
	for _, v := range value.Objects {
		result.Objects = append(result.Objects, &runtimev1.PermissionAuthoringObjectGrant{ResourceType: v.ResourceType, Read: v.Read, Create: v.Create, Edit: v.Edit, Delete: v.Delete, ViewAll: v.ViewAll, ModifyAll: v.ModifyAll})
	}
	for _, v := range value.Fields {
		result.Fields = append(result.Fields, &runtimev1.PermissionAuthoringFieldGrant{ResourceType: v.ResourceType, FieldName: v.FieldName, Read: v.Read, Edit: v.Edit})
	}
	for _, v := range value.RecordTypes {
		result.RecordTypes = append(result.RecordTypes, &runtimev1.PermissionAuthoringRecordTypeGrant{RecordTypeId: v.RecordTypeID, Visible: v.Visible})
	}
	for _, v := range value.Custom {
		result.Custom = append(result.Custom, &runtimev1.PermissionAuthoringCapabilityGrant{CapabilityId: v.CapabilityID, Enabled: v.Enabled})
	}
	return result
}

func fromWirePermissionAuthoringStoredGrants(value *runtimev1.PermissionAuthoringStoredGrants) (semantic.StoredGrants, bool) {
	result := semantic.StoredGrants{}
	for _, v := range value.GetSystem() {
		if v == nil {
			return semantic.StoredGrants{}, false
		}
		result.System = append(result.System, semantic.CapabilityGrant{CapabilityID: v.GetCapabilityId(), Enabled: v.GetEnabled()})
	}
	for _, v := range value.GetObjects() {
		if v == nil {
			return semantic.StoredGrants{}, false
		}
		result.Objects = append(result.Objects, semantic.ObjectGrant{ResourceType: v.GetResourceType(), Read: v.GetRead(), Create: v.GetCreate(), Edit: v.GetEdit(), Delete: v.GetDelete(), ViewAll: v.GetViewAll(), ModifyAll: v.GetModifyAll()})
	}
	for _, v := range value.GetFields() {
		if v == nil {
			return semantic.StoredGrants{}, false
		}
		result.Fields = append(result.Fields, semantic.FieldGrant{ResourceType: v.GetResourceType(), FieldName: v.GetFieldName(), Read: v.GetRead(), Edit: v.GetEdit()})
	}
	for _, v := range value.GetRecordTypes() {
		if v == nil {
			return semantic.StoredGrants{}, false
		}
		result.RecordTypes = append(result.RecordTypes, semantic.RecordTypeGrant{RecordTypeID: v.GetRecordTypeId(), Visible: v.GetVisible()})
	}
	for _, v := range value.GetCustom() {
		if v == nil {
			return semantic.StoredGrants{}, false
		}
		result.Custom = append(result.Custom, semantic.CapabilityGrant{CapabilityID: v.GetCapabilityId(), Enabled: v.GetEnabled()})
	}
	return result, true
}

func toWirePermissionAuthoringChanges(value semantic.Changes) *runtimev1.PermissionAuthoringChanges {
	result := &runtimev1.PermissionAuthoringChanges{}
	for _, v := range value.System {
		result.System = append(result.System, &runtimev1.PermissionAuthoringCapabilityGrantChange{CapabilityId: v.CapabilityID, Enabled: v.Enabled})
	}
	for _, v := range value.Objects {
		result.Objects = append(result.Objects, &runtimev1.PermissionAuthoringObjectGrantChange{ResourceType: v.ResourceType, Read: v.Read, Create: v.Create, Edit: v.Edit, Delete: v.Delete, ViewAll: v.ViewAll, ModifyAll: v.ModifyAll})
	}
	for _, v := range value.Fields {
		result.Fields = append(result.Fields, &runtimev1.PermissionAuthoringFieldGrantChange{ResourceType: v.ResourceType, FieldName: v.FieldName, Read: v.Read, Edit: v.Edit})
	}
	for _, v := range value.RecordTypes {
		result.RecordTypes = append(result.RecordTypes, &runtimev1.PermissionAuthoringRecordTypeGrantChange{RecordTypeId: v.RecordTypeID, Visible: v.Visible, ResourceType: v.ResourceType})
	}
	for _, v := range value.Custom {
		result.Custom = append(result.Custom, &runtimev1.PermissionAuthoringCapabilityGrantChange{CapabilityId: v.CapabilityID, Enabled: v.Enabled})
	}
	return result
}

func fromWirePermissionAuthoringChanges(value *runtimev1.PermissionAuthoringChanges) (semantic.Changes, bool) {
	result := semantic.Changes{}
	for _, v := range value.GetSystem() {
		if v == nil {
			return semantic.Changes{}, false
		}
		result.System = append(result.System, semantic.CapabilityGrantChange{CapabilityID: v.GetCapabilityId(), Enabled: v.GetEnabled()})
	}
	for _, v := range value.GetObjects() {
		if v == nil {
			return semantic.Changes{}, false
		}
		result.Objects = append(result.Objects, semantic.ObjectGrantChange{ResourceType: v.GetResourceType(), Read: v.GetRead(), Create: v.GetCreate(), Edit: v.GetEdit(), Delete: v.GetDelete(), ViewAll: v.GetViewAll(), ModifyAll: v.GetModifyAll()})
	}
	for _, v := range value.GetFields() {
		if v == nil {
			return semantic.Changes{}, false
		}
		result.Fields = append(result.Fields, semantic.FieldGrantChange{ResourceType: v.GetResourceType(), FieldName: v.GetFieldName(), Read: v.GetRead(), Edit: v.GetEdit()})
	}
	for _, v := range value.GetRecordTypes() {
		if v == nil {
			return semantic.Changes{}, false
		}
		result.RecordTypes = append(result.RecordTypes, semantic.RecordTypeGrantChange{RecordTypeID: v.GetRecordTypeId(), ResourceType: v.GetResourceType(), Visible: v.GetVisible()})
	}
	for _, v := range value.GetCustom() {
		if v == nil {
			return semantic.Changes{}, false
		}
		result.Custom = append(result.Custom, semantic.CapabilityGrantChange{CapabilityID: v.GetCapabilityId(), Enabled: v.GetEnabled()})
	}
	return result, true
}

func toWirePermissionAuthoringTargetKind(value semantic.TargetKind) runtimev1.PermissionAuthoringTargetKind {
	if value == semantic.TargetProfile {
		return runtimev1.PermissionAuthoringTargetKind_PERMISSION_AUTHORING_TARGET_KIND_PROFILE
	}
	if value == semantic.TargetPermissionSet {
		return runtimev1.PermissionAuthoringTargetKind_PERMISSION_AUTHORING_TARGET_KIND_PERMISSION_SET
	}
	return runtimev1.PermissionAuthoringTargetKind_PERMISSION_AUTHORING_TARGET_KIND_UNSPECIFIED
}
func fromWirePermissionAuthoringTargetKind(value runtimev1.PermissionAuthoringTargetKind) (semantic.TargetKind, bool) {
	if value == runtimev1.PermissionAuthoringTargetKind_PERMISSION_AUTHORING_TARGET_KIND_PROFILE {
		return semantic.TargetProfile, true
	}
	if value == runtimev1.PermissionAuthoringTargetKind_PERMISSION_AUTHORING_TARGET_KIND_PERMISSION_SET {
		return semantic.TargetPermissionSet, true
	}
	return "", false
}
func toWirePermissionAuthoringOutcome(value semantic.Outcome) runtimev1.PermissionAuthoringOutcome {
	switch value {
	case semantic.OutcomeApplied:
		return runtimev1.PermissionAuthoringOutcome_PERMISSION_AUTHORING_OUTCOME_APPLIED
	case semantic.OutcomeNoop:
		return runtimev1.PermissionAuthoringOutcome_PERMISSION_AUTHORING_OUTCOME_NOOP
	case semantic.OutcomeRejected:
		return runtimev1.PermissionAuthoringOutcome_PERMISSION_AUTHORING_OUTCOME_REJECTED
	}
	return runtimev1.PermissionAuthoringOutcome_PERMISSION_AUTHORING_OUTCOME_UNSPECIFIED
}
func fromWirePermissionAuthoringOutcome(value runtimev1.PermissionAuthoringOutcome) (semantic.Outcome, bool) {
	switch value {
	case runtimev1.PermissionAuthoringOutcome_PERMISSION_AUTHORING_OUTCOME_APPLIED:
		return semantic.OutcomeApplied, true
	case runtimev1.PermissionAuthoringOutcome_PERMISSION_AUTHORING_OUTCOME_NOOP:
		return semantic.OutcomeNoop, true
	case runtimev1.PermissionAuthoringOutcome_PERMISSION_AUTHORING_OUTCOME_REJECTED:
		return semantic.OutcomeRejected, true
	}
	return "", false
}
func toWirePermissionAuthoringRejection(value semantic.RejectionCode) runtimev1.PermissionAuthoringRejectionCode {
	switch value {
	case semantic.RejectionDenied:
		return runtimev1.PermissionAuthoringRejectionCode_PERMISSION_AUTHORING_REJECTION_CODE_DENIED
	case semantic.RejectionMissing:
		return runtimev1.PermissionAuthoringRejectionCode_PERMISSION_AUTHORING_REJECTION_CODE_MISSING
	case semantic.RejectionStaleAuthoringState:
		return runtimev1.PermissionAuthoringRejectionCode_PERMISSION_AUTHORING_REJECTION_CODE_STALE_AUTHORING_STATE
	case semantic.RejectionInvalidChange:
		return runtimev1.PermissionAuthoringRejectionCode_PERMISSION_AUTHORING_REJECTION_CODE_INVALID_CHANGE
	case semantic.RejectionConflict:
		return runtimev1.PermissionAuthoringRejectionCode_PERMISSION_AUTHORING_REJECTION_CODE_CONFLICT
	}
	return runtimev1.PermissionAuthoringRejectionCode_PERMISSION_AUTHORING_REJECTION_CODE_UNSPECIFIED
}
func fromWirePermissionAuthoringRejection(value runtimev1.PermissionAuthoringRejectionCode) (semantic.RejectionCode, bool) {
	switch value {
	case runtimev1.PermissionAuthoringRejectionCode_PERMISSION_AUTHORING_REJECTION_CODE_UNSPECIFIED:
		return semantic.RejectionNone, true
	case runtimev1.PermissionAuthoringRejectionCode_PERMISSION_AUTHORING_REJECTION_CODE_DENIED:
		return semantic.RejectionDenied, true
	case runtimev1.PermissionAuthoringRejectionCode_PERMISSION_AUTHORING_REJECTION_CODE_MISSING:
		return semantic.RejectionMissing, true
	case runtimev1.PermissionAuthoringRejectionCode_PERMISSION_AUTHORING_REJECTION_CODE_STALE_AUTHORING_STATE:
		return semantic.RejectionStaleAuthoringState, true
	case runtimev1.PermissionAuthoringRejectionCode_PERMISSION_AUTHORING_REJECTION_CODE_INVALID_CHANGE:
		return semantic.RejectionInvalidChange, true
	case runtimev1.PermissionAuthoringRejectionCode_PERMISSION_AUTHORING_REJECTION_CODE_CONFLICT:
		return semantic.RejectionConflict, true
	}
	return "", false
}
func toWirePermissionAuthoringCommandState(value semantic.CommandState) runtimev1.PermissionAuthoringCommandState {
	switch value {
	case semantic.CommandAccepted:
		return runtimev1.PermissionAuthoringCommandState_PERMISSION_AUTHORING_COMMAND_STATE_ACCEPTED
	case semantic.CommandExecuting:
		return runtimev1.PermissionAuthoringCommandState_PERMISSION_AUTHORING_COMMAND_STATE_EXECUTING
	case semantic.CommandCompleted:
		return runtimev1.PermissionAuthoringCommandState_PERMISSION_AUTHORING_COMMAND_STATE_COMPLETED
	}
	return runtimev1.PermissionAuthoringCommandState_PERMISSION_AUTHORING_COMMAND_STATE_UNSPECIFIED
}
func fromWirePermissionAuthoringCommandState(value runtimev1.PermissionAuthoringCommandState) (semantic.CommandState, bool) {
	switch value {
	case runtimev1.PermissionAuthoringCommandState_PERMISSION_AUTHORING_COMMAND_STATE_ACCEPTED:
		return semantic.CommandAccepted, true
	case runtimev1.PermissionAuthoringCommandState_PERMISSION_AUTHORING_COMMAND_STATE_EXECUTING:
		return semantic.CommandExecuting, true
	case runtimev1.PermissionAuthoringCommandState_PERMISSION_AUTHORING_COMMAND_STATE_COMPLETED:
		return semantic.CommandCompleted, true
	}
	return "", false
}

func requirePermissionAuthoringMapping(values ...any) error {
	if err := requirePlatformSemanticShape(semantic.CapabilityName); err != nil {
		return err
	}
	for _, value := range values {
		revisioned, ok := value.(permissionAuthoringSemanticMappingRevisioner)
		if !ok || revisioned.PermissionAuthoringSemanticMappingRevision() != supportedPermissionAuthoringSemanticMappingRevision {
			return incompatibleFailureFor(platformCapability(semantic.CapabilityName))
		}
	}
	return nil
}
