package mapping

import (
	"context"

	approvalsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/approvalv1"
	runtimev1 "github.com/pingcap-inc/nexuscrm-contract/wire-go/gen/runtime/v1"
)

func ToWireExecuteApprovalRequest(ctx context.Context, request approvalsemantic.ExecuteRequest) (*runtimev1.ExecuteApprovalRequest, error) {
	if err := requirePlatformSemanticShape(approvalsemantic.ExecuteCapabilityName); err != nil {
		return nil, err
	}
	if err := approvalsemantic.ValidateExecuteRequest(ctx, request); err != nil {
		return nil, err
	}
	operation, ok := toWireApprovalOperation(request.Operation)
	if !ok {
		return nil, invalidPlatformWire()
	}
	return &runtimev1.ExecuteApprovalRequest{
		Operation: operation, IdempotencyKey: request.IdempotencyKey,
		ObjectId: request.ObjectID, TargetRecordId: request.TargetRecordID,
		WorkItemId: request.WorkItemID, Comments: request.Comments,
		NextActorId: request.NextActorID, SkipEntryCriteria: request.SkipEntryCriteria,
		MinCatalogRevision: request.MinCatalogRevision,
	}, nil
}

func FromWireExecuteApprovalRequest(ctx context.Context, request *runtimev1.ExecuteApprovalRequest) (approvalsemantic.ExecuteRequest, error) {
	if err := requirePlatformSemanticShape(approvalsemantic.ExecuteCapabilityName); err != nil {
		return approvalsemantic.ExecuteRequest{}, err
	}
	if request == nil {
		return approvalsemantic.ExecuteRequest{}, invalidPlatformWire()
	}
	operation, ok := fromWireApprovalOperation(request.GetOperation())
	if !ok {
		return approvalsemantic.ExecuteRequest{}, invalidPlatformWire()
	}
	result := approvalsemantic.ExecuteRequest{
		Operation: operation, IdempotencyKey: request.GetIdempotencyKey(),
		ObjectID: request.GetObjectId(), TargetRecordID: request.GetTargetRecordId(),
		WorkItemID: request.GetWorkItemId(), Comments: request.GetComments(),
		NextActorID: request.GetNextActorId(), SkipEntryCriteria: request.GetSkipEntryCriteria(),
		MinCatalogRevision: request.MinCatalogRevision,
	}
	if err := approvalsemantic.ValidateExecuteRequest(ctx, result); err != nil {
		return approvalsemantic.ExecuteRequest{}, err
	}
	return result, nil
}

func ToWireExecuteApprovalResponse(request approvalsemantic.ExecuteRequest, response approvalsemantic.ExecuteResponse) (*runtimev1.ExecuteApprovalResponse, error) {
	if err := requirePlatformSemanticShape(approvalsemantic.ExecuteCapabilityName); err != nil {
		return nil, err
	}
	if err := approvalsemantic.ValidateExecuteResponse(request, response); err != nil {
		return nil, err
	}
	state := runtimev1.ApprovalInstanceState_APPROVAL_INSTANCE_STATE_UNSPECIFIED
	if response.SubmitRejection == nil {
		var ok bool
		state, ok = toWireApprovalInstanceState(response.State)
		if !ok {
			return nil, internalPlatformWire()
		}
	}
	result := &runtimev1.ExecuteApprovalResponse{
		ExecutionId: response.ExecutionID, InstanceId: response.InstanceID,
		TargetRecordId: response.TargetRecordID, SourceWorkItemId: response.SourceWorkItemID,
		ActingPrincipalId: response.ActingPrincipalID,
		State:             state,
		PendingWorkItems:  make([]*runtimev1.ApprovalWorkItemAssignment, 0, len(response.PendingWorkItems)),
		ActionFailures:    make([]*runtimev1.ApprovalActionFailure, 0, len(response.ActionFailures)),
		Receipts:          toWireReceipts(response.Receipts, platformCapability(approvalsemantic.ExecuteCapabilityName)),
	}
	if response.SubmitRejection != nil {
		reason, ok := toWireApprovalSubmitRejectionReason(response.SubmitRejection.Reason)
		if !ok {
			return nil, internalPlatformWire()
		}
		result.SubmitRejection = &runtimev1.ApprovalSubmitRejection{
			Reason: reason,
		}
		if len(response.SubmitRejection.ValidationIssues) > 0 {
			result.SubmitRejection.ValidationIssues = make(
				[]*runtimev1.ApprovalValidationIssue,
				0,
				len(response.SubmitRejection.ValidationIssues),
			)
		}
		for _, issue := range response.SubmitRejection.ValidationIssues {
			result.SubmitRejection.ValidationIssues = append(
				result.SubmitRejection.ValidationIssues,
				&runtimev1.ApprovalValidationIssue{
					RuleName: issue.RuleName, Field: issue.Field, Message: issue.Message,
				},
			)
		}
	}
	for _, assignment := range response.PendingWorkItems {
		result.PendingWorkItems = append(result.PendingWorkItems, &runtimev1.ApprovalWorkItemAssignment{
			WorkItemId: assignment.WorkItemID, ActorId: assignment.ActorID,
		})
	}
	for _, failure := range response.ActionFailures {
		kind, kindOK := toWireApprovalActionFailureKind(failure.Kind)
		reason, reasonOK := toWireApprovalActionFailureReason(failure.Reason)
		if !kindOK || !reasonOK {
			return nil, internalPlatformWire()
		}
		result.ActionFailures = append(result.ActionFailures, &runtimev1.ApprovalActionFailure{
			ActionRef: failure.ActionRef, Kind: kind, Reason: reason,
		})
	}
	return result, nil
}

func FromWireExecuteApprovalResponse(request approvalsemantic.ExecuteRequest, response *runtimev1.ExecuteApprovalResponse) (approvalsemantic.ExecuteResponse, error) {
	if err := requirePlatformSemanticShape(approvalsemantic.ExecuteCapabilityName); err != nil {
		return approvalsemantic.ExecuteResponse{}, err
	}
	if response == nil || response.GetReceipts() == nil {
		return approvalsemantic.ExecuteResponse{}, incompatibleFailureFor(platformCapability(approvalsemantic.ExecuteCapabilityName))
	}
	if len(response.GetSubmitRejection().GetValidationIssues()) > approvalsemantic.MaxValidationIssues {
		return approvalsemantic.ExecuteResponse{}, internalPlatformWire()
	}
	state := approvalsemantic.InstanceState("")
	if response.GetSubmitRejection() == nil {
		var ok bool
		state, ok = fromWireApprovalInstanceState(response.GetState())
		if !ok {
			return approvalsemantic.ExecuteResponse{}, internalPlatformWire()
		}
	} else if response.GetState() != runtimev1.ApprovalInstanceState_APPROVAL_INSTANCE_STATE_UNSPECIFIED {
		// SubmitRejection is the wire union's non-applied arm. Never discard a
		// second, conflicting applied-state discriminator.
		return approvalsemantic.ExecuteResponse{}, internalPlatformWire()
	}
	receipts, err := fromWireReceipts(response.GetReceipts(), platformCapability(approvalsemantic.ExecuteCapabilityName))
	if err != nil {
		return approvalsemantic.ExecuteResponse{}, err
	}
	result := approvalsemantic.ExecuteResponse{
		ExecutionID: response.GetExecutionId(), InstanceID: response.GetInstanceId(),
		TargetRecordID: response.GetTargetRecordId(), SourceWorkItemID: response.GetSourceWorkItemId(),
		ActingPrincipalID: response.GetActingPrincipalId(),
		State:             state, PendingWorkItems: make([]approvalsemantic.WorkItemAssignment, 0, len(response.GetPendingWorkItems())),
		ActionFailures: make([]approvalsemantic.ActionFailure, 0, len(response.GetActionFailures())), Receipts: receipts,
	}
	if response.GetSubmitRejection() != nil {
		reason, ok := fromWireApprovalSubmitRejectionReason(response.GetSubmitRejection().GetReason())
		if !ok {
			return approvalsemantic.ExecuteResponse{}, internalPlatformWire()
		}
		result.SubmitRejection = &approvalsemantic.SubmitRejection{
			Reason: reason,
		}
		if len(response.GetSubmitRejection().GetValidationIssues()) > 0 {
			result.SubmitRejection.ValidationIssues = make(
				[]approvalsemantic.ValidationIssue,
				0,
				len(response.GetSubmitRejection().GetValidationIssues()),
			)
		}
		for _, issue := range response.GetSubmitRejection().GetValidationIssues() {
			if issue == nil {
				return approvalsemantic.ExecuteResponse{}, internalPlatformWire()
			}
			result.SubmitRejection.ValidationIssues = append(
				result.SubmitRejection.ValidationIssues,
				approvalsemantic.ValidationIssue{
					RuleName: issue.GetRuleName(), Field: issue.GetField(), Message: issue.GetMessage(),
				},
			)
		}
	}
	for _, assignment := range response.GetPendingWorkItems() {
		if assignment == nil {
			return approvalsemantic.ExecuteResponse{}, internalPlatformWire()
		}
		result.PendingWorkItems = append(result.PendingWorkItems, approvalsemantic.WorkItemAssignment{
			WorkItemID: assignment.GetWorkItemId(), ActorID: assignment.GetActorId(),
		})
	}
	for _, failure := range response.GetActionFailures() {
		if failure == nil {
			return approvalsemantic.ExecuteResponse{}, internalPlatformWire()
		}
		kind, kindOK := fromWireApprovalActionFailureKind(failure.GetKind())
		reason, reasonOK := fromWireApprovalActionFailureReason(failure.GetReason())
		if !kindOK || !reasonOK {
			return approvalsemantic.ExecuteResponse{}, internalPlatformWire()
		}
		result.ActionFailures = append(result.ActionFailures, approvalsemantic.ActionFailure{
			ActionRef: failure.GetActionRef(), Kind: kind, Reason: reason,
		})
	}
	if err := approvalsemantic.ValidateExecuteResponse(request, result); err != nil {
		return approvalsemantic.ExecuteResponse{}, err
	}
	return result, nil
}

func ToWireReadApprovalRequest(ctx context.Context, request approvalsemantic.ReadRequest) (*runtimev1.ReadApprovalRequest, error) {
	if err := requirePlatformSemanticShape(approvalsemantic.ReadCapabilityName); err != nil {
		return nil, err
	}
	if err := approvalsemantic.ValidateReadRequest(ctx, request); err != nil {
		return nil, err
	}
	kind, ok := toWireApprovalReadKind(request.Kind)
	if !ok {
		return nil, invalidPlatformWire()
	}
	return &runtimev1.ReadApprovalRequest{
		Kind: kind, TargetRecordId: request.TargetRecordID,
		MinCatalogRevision: request.MinCatalogRevision,
	}, nil
}

func FromWireReadApprovalRequest(ctx context.Context, request *runtimev1.ReadApprovalRequest) (approvalsemantic.ReadRequest, error) {
	if err := requirePlatformSemanticShape(approvalsemantic.ReadCapabilityName); err != nil {
		return approvalsemantic.ReadRequest{}, err
	}
	if request == nil {
		return approvalsemantic.ReadRequest{}, invalidPlatformWire()
	}
	kind, ok := fromWireApprovalReadKind(request.GetKind())
	if !ok {
		return approvalsemantic.ReadRequest{}, invalidPlatformWire()
	}
	result := approvalsemantic.ReadRequest{
		Kind: kind, TargetRecordID: request.GetTargetRecordId(),
		MinCatalogRevision: request.MinCatalogRevision,
	}
	if err := approvalsemantic.ValidateReadRequest(ctx, result); err != nil {
		return approvalsemantic.ReadRequest{}, err
	}
	return result, nil
}

func ToWireReadApprovalResponse(request approvalsemantic.ReadRequest, response approvalsemantic.ReadResponse) (*runtimev1.ReadApprovalResponse, error) {
	if err := requirePlatformSemanticShape(approvalsemantic.ReadCapabilityName); err != nil {
		return nil, err
	}
	if err := approvalsemantic.ValidateReadResponse(request, response); err != nil {
		return nil, err
	}
	result := &runtimev1.ReadApprovalResponse{
		Pending:  make([]*runtimev1.ApprovalPendingItem, 0, len(response.Pending)),
		Steps:    make([]*runtimev1.ApprovalStepDisplay, 0, len(response.Steps)),
		Receipts: toWireReceipts(response.Receipts, platformCapability(approvalsemantic.ReadCapabilityName)),
	}
	for _, item := range response.Pending {
		result.Pending = append(result.Pending, &runtimev1.ApprovalPendingItem{
			WorkItemId: item.WorkItemID, InstanceId: item.InstanceID, DefinitionId: item.DefinitionID,
			TargetRecordId: item.TargetRecordID, ObjectId: item.ObjectID,
			SubmittedById: item.SubmittedByID, SubmittedByName: item.SubmittedByName,
			SubmittedAt: item.SubmittedAt, ActorId: item.ActorID, OriginalActorId: item.OriginalActorID,
			Comments: item.Comments, RecordName: item.RecordName,
		})
	}
	if response.Latest != nil {
		latest, err := toWireApprovalInstanceSummary(*response.Latest)
		if err != nil {
			return nil, err
		}
		result.Latest = latest
	}
	for _, step := range response.Steps {
		behavior, ok := toWireApprovalStepNoMatchBehavior(step.NoMatchBehavior)
		if !ok {
			return nil, internalPlatformWire()
		}
		result.Steps = append(result.Steps, &runtimev1.ApprovalStepDisplay{
			StepId: step.StepID, StepOrder: step.StepOrder, StepName: step.StepName,
			StepLabel: step.StepLabel, HasCriteria: step.HasCriteria, NoMatchBehavior: behavior,
		})
	}
	return result, nil
}

func FromWireReadApprovalResponse(request approvalsemantic.ReadRequest, response *runtimev1.ReadApprovalResponse) (approvalsemantic.ReadResponse, error) {
	if err := requirePlatformSemanticShape(approvalsemantic.ReadCapabilityName); err != nil {
		return approvalsemantic.ReadResponse{}, err
	}
	if response == nil || response.GetReceipts() == nil {
		return approvalsemantic.ReadResponse{}, incompatibleFailureFor(platformCapability(approvalsemantic.ReadCapabilityName))
	}
	receipts, err := fromWireReceipts(response.GetReceipts(), platformCapability(approvalsemantic.ReadCapabilityName))
	if err != nil {
		return approvalsemantic.ReadResponse{}, err
	}
	result := approvalsemantic.ReadResponse{
		Pending: make([]approvalsemantic.PendingItem, 0, len(response.GetPending())),
		Steps:   make([]approvalsemantic.StepDisplay, 0, len(response.GetSteps())), Receipts: receipts,
	}
	for _, item := range response.GetPending() {
		if item == nil {
			return approvalsemantic.ReadResponse{}, internalPlatformWire()
		}
		result.Pending = append(result.Pending, approvalsemantic.PendingItem{
			WorkItemID: item.GetWorkItemId(), InstanceID: item.GetInstanceId(), DefinitionID: item.GetDefinitionId(),
			TargetRecordID: item.GetTargetRecordId(), ObjectID: item.GetObjectId(),
			SubmittedByID: item.GetSubmittedById(), SubmittedByName: item.GetSubmittedByName(),
			SubmittedAt: item.GetSubmittedAt(), ActorID: item.GetActorId(), OriginalActorID: item.GetOriginalActorId(),
			Comments: item.GetComments(), RecordName: item.GetRecordName(),
		})
	}
	if response.GetLatest() != nil {
		latest, err := fromWireApprovalInstanceSummary(response.GetLatest())
		if err != nil {
			return approvalsemantic.ReadResponse{}, err
		}
		result.Latest = &latest
	}
	for _, step := range response.GetSteps() {
		if step == nil {
			return approvalsemantic.ReadResponse{}, internalPlatformWire()
		}
		behavior, ok := fromWireApprovalStepNoMatchBehavior(step.GetNoMatchBehavior())
		if !ok {
			return approvalsemantic.ReadResponse{}, internalPlatformWire()
		}
		result.Steps = append(result.Steps, approvalsemantic.StepDisplay{
			StepID: step.GetStepId(), StepOrder: step.GetStepOrder(), StepName: step.GetStepName(),
			StepLabel: step.GetStepLabel(), HasCriteria: step.GetHasCriteria(), NoMatchBehavior: behavior,
		})
	}
	if err := approvalsemantic.ValidateReadResponse(request, result); err != nil {
		return approvalsemantic.ReadResponse{}, err
	}
	return result, nil
}

func toWireApprovalInstanceSummary(value approvalsemantic.InstanceSummary) (*runtimev1.ApprovalInstanceSummary, error) {
	state, ok := toWireApprovalInstanceState(value.State)
	if !ok {
		return nil, internalPlatformWire()
	}
	result := &runtimev1.ApprovalInstanceSummary{
		InstanceId: value.InstanceID, DefinitionId: value.DefinitionID, TargetRecordId: value.TargetRecordID,
		State: state, SubmittedById: value.SubmittedByID, SubmittedByName: value.SubmittedByName,
		CreatedAt: value.CreatedAt, CompletedAt: value.CompletedAt,
		PendingWorkItems: make([]*runtimev1.ApprovalPendingWorkItem, 0, len(value.PendingWorkItems)),
	}
	for _, item := range value.PendingWorkItems {
		result.PendingWorkItems = append(result.PendingWorkItems, &runtimev1.ApprovalPendingWorkItem{
			WorkItemId: item.WorkItemID, ActorId: item.ActorID, ActorName: item.ActorName,
			OriginalActorId: item.OriginalActorID, OriginalActorName: item.OriginalActorName,
		})
	}
	return result, nil
}

func fromWireApprovalInstanceSummary(value *runtimev1.ApprovalInstanceSummary) (approvalsemantic.InstanceSummary, error) {
	if value == nil {
		return approvalsemantic.InstanceSummary{}, internalPlatformWire()
	}
	state, ok := fromWireApprovalInstanceState(value.GetState())
	if !ok {
		return approvalsemantic.InstanceSummary{}, internalPlatformWire()
	}
	result := approvalsemantic.InstanceSummary{
		InstanceID: value.GetInstanceId(), DefinitionID: value.GetDefinitionId(), TargetRecordID: value.GetTargetRecordId(),
		State: state, SubmittedByID: value.GetSubmittedById(), SubmittedByName: value.GetSubmittedByName(),
		CreatedAt: value.GetCreatedAt(), CompletedAt: value.GetCompletedAt(),
		PendingWorkItems: make([]approvalsemantic.PendingWorkItem, 0, len(value.GetPendingWorkItems())),
	}
	for _, item := range value.GetPendingWorkItems() {
		if item == nil {
			return approvalsemantic.InstanceSummary{}, internalPlatformWire()
		}
		result.PendingWorkItems = append(result.PendingWorkItems, approvalsemantic.PendingWorkItem{
			WorkItemID: item.GetWorkItemId(), ActorID: item.GetActorId(), ActorName: item.GetActorName(),
			OriginalActorID: item.GetOriginalActorId(), OriginalActorName: item.GetOriginalActorName(),
		})
	}
	return result, nil
}

func toWireApprovalOperation(value approvalsemantic.Operation) (runtimev1.ApprovalOperation, bool) {
	switch value {
	case approvalsemantic.OperationSubmit:
		return runtimev1.ApprovalOperation_APPROVAL_OPERATION_SUBMIT, true
	case approvalsemantic.OperationApprove:
		return runtimev1.ApprovalOperation_APPROVAL_OPERATION_APPROVE, true
	case approvalsemantic.OperationReject:
		return runtimev1.ApprovalOperation_APPROVAL_OPERATION_REJECT, true
	case approvalsemantic.OperationRecall:
		return runtimev1.ApprovalOperation_APPROVAL_OPERATION_RECALL, true
	case approvalsemantic.OperationReassign:
		return runtimev1.ApprovalOperation_APPROVAL_OPERATION_REASSIGN, true
	default:
		return runtimev1.ApprovalOperation_APPROVAL_OPERATION_UNSPECIFIED, false
	}
}

func fromWireApprovalOperation(value runtimev1.ApprovalOperation) (approvalsemantic.Operation, bool) {
	switch value {
	case runtimev1.ApprovalOperation_APPROVAL_OPERATION_SUBMIT:
		return approvalsemantic.OperationSubmit, true
	case runtimev1.ApprovalOperation_APPROVAL_OPERATION_APPROVE:
		return approvalsemantic.OperationApprove, true
	case runtimev1.ApprovalOperation_APPROVAL_OPERATION_REJECT:
		return approvalsemantic.OperationReject, true
	case runtimev1.ApprovalOperation_APPROVAL_OPERATION_RECALL:
		return approvalsemantic.OperationRecall, true
	case runtimev1.ApprovalOperation_APPROVAL_OPERATION_REASSIGN:
		return approvalsemantic.OperationReassign, true
	default:
		return "", false
	}
}

func toWireApprovalInstanceState(value approvalsemantic.InstanceState) (runtimev1.ApprovalInstanceState, bool) {
	switch value {
	case approvalsemantic.InstanceStatePending:
		return runtimev1.ApprovalInstanceState_APPROVAL_INSTANCE_STATE_PENDING, true
	case approvalsemantic.InstanceStateApproved:
		return runtimev1.ApprovalInstanceState_APPROVAL_INSTANCE_STATE_APPROVED, true
	case approvalsemantic.InstanceStateRejected:
		return runtimev1.ApprovalInstanceState_APPROVAL_INSTANCE_STATE_REJECTED, true
	case approvalsemantic.InstanceStateWithdrawn:
		return runtimev1.ApprovalInstanceState_APPROVAL_INSTANCE_STATE_WITHDRAWN, true
	default:
		return runtimev1.ApprovalInstanceState_APPROVAL_INSTANCE_STATE_UNSPECIFIED, false
	}
}

func fromWireApprovalInstanceState(value runtimev1.ApprovalInstanceState) (approvalsemantic.InstanceState, bool) {
	switch value {
	case runtimev1.ApprovalInstanceState_APPROVAL_INSTANCE_STATE_PENDING:
		return approvalsemantic.InstanceStatePending, true
	case runtimev1.ApprovalInstanceState_APPROVAL_INSTANCE_STATE_APPROVED:
		return approvalsemantic.InstanceStateApproved, true
	case runtimev1.ApprovalInstanceState_APPROVAL_INSTANCE_STATE_REJECTED:
		return approvalsemantic.InstanceStateRejected, true
	case runtimev1.ApprovalInstanceState_APPROVAL_INSTANCE_STATE_WITHDRAWN:
		return approvalsemantic.InstanceStateWithdrawn, true
	default:
		return "", false
	}
}

func toWireApprovalSubmitRejectionReason(value approvalsemantic.SubmitRejectionReason) (runtimev1.ApprovalSubmitRejectionReason, bool) {
	switch value {
	case approvalsemantic.SubmitRejectionNoActiveProcess:
		return runtimev1.ApprovalSubmitRejectionReason_APPROVAL_SUBMIT_REJECTION_REASON_NO_ACTIVE_PROCESS, true
	case approvalsemantic.SubmitRejectionEntryCriteriaMiss:
		return runtimev1.ApprovalSubmitRejectionReason_APPROVAL_SUBMIT_REJECTION_REASON_ENTRY_CRITERIA_NOT_MET, true
	case approvalsemantic.SubmitRejectionRecordValidationFailed:
		return runtimev1.ApprovalSubmitRejectionReason_APPROVAL_SUBMIT_REJECTION_REASON_RECORD_VALIDATION_FAILED, true
	default:
		return runtimev1.ApprovalSubmitRejectionReason_APPROVAL_SUBMIT_REJECTION_REASON_UNSPECIFIED, false
	}
}

func fromWireApprovalSubmitRejectionReason(value runtimev1.ApprovalSubmitRejectionReason) (approvalsemantic.SubmitRejectionReason, bool) {
	switch value {
	case runtimev1.ApprovalSubmitRejectionReason_APPROVAL_SUBMIT_REJECTION_REASON_NO_ACTIVE_PROCESS:
		return approvalsemantic.SubmitRejectionNoActiveProcess, true
	case runtimev1.ApprovalSubmitRejectionReason_APPROVAL_SUBMIT_REJECTION_REASON_ENTRY_CRITERIA_NOT_MET:
		return approvalsemantic.SubmitRejectionEntryCriteriaMiss, true
	case runtimev1.ApprovalSubmitRejectionReason_APPROVAL_SUBMIT_REJECTION_REASON_RECORD_VALIDATION_FAILED:
		return approvalsemantic.SubmitRejectionRecordValidationFailed, true
	default:
		return "", false
	}
}

func toWireApprovalActionFailureKind(value approvalsemantic.ActionFailureKind) (runtimev1.ApprovalActionFailureKind, bool) {
	switch value {
	case approvalsemantic.ActionFailureAlert:
		return runtimev1.ApprovalActionFailureKind_APPROVAL_ACTION_FAILURE_KIND_ALERT, true
	case approvalsemantic.ActionFailureFlow:
		return runtimev1.ApprovalActionFailureKind_APPROVAL_ACTION_FAILURE_KIND_FLOW, true
	case approvalsemantic.ActionFailureUnsupported:
		return runtimev1.ApprovalActionFailureKind_APPROVAL_ACTION_FAILURE_KIND_UNSUPPORTED, true
	default:
		return runtimev1.ApprovalActionFailureKind_APPROVAL_ACTION_FAILURE_KIND_UNSPECIFIED, false
	}
}

func fromWireApprovalActionFailureKind(value runtimev1.ApprovalActionFailureKind) (approvalsemantic.ActionFailureKind, bool) {
	switch value {
	case runtimev1.ApprovalActionFailureKind_APPROVAL_ACTION_FAILURE_KIND_ALERT:
		return approvalsemantic.ActionFailureAlert, true
	case runtimev1.ApprovalActionFailureKind_APPROVAL_ACTION_FAILURE_KIND_FLOW:
		return approvalsemantic.ActionFailureFlow, true
	case runtimev1.ApprovalActionFailureKind_APPROVAL_ACTION_FAILURE_KIND_UNSUPPORTED:
		return approvalsemantic.ActionFailureUnsupported, true
	default:
		return "", false
	}
}

func toWireApprovalActionFailureReason(value approvalsemantic.ActionFailureReason) (runtimev1.ApprovalActionFailureReason, bool) {
	switch value {
	case approvalsemantic.ActionFailureUnavailable:
		return runtimev1.ApprovalActionFailureReason_APPROVAL_ACTION_FAILURE_REASON_UNAVAILABLE, true
	case approvalsemantic.ActionFailureInvalidBinding:
		return runtimev1.ApprovalActionFailureReason_APPROVAL_ACTION_FAILURE_REASON_INVALID_BINDING, true
	case approvalsemantic.ActionFailureUnsafeDefinition:
		return runtimev1.ApprovalActionFailureReason_APPROVAL_ACTION_FAILURE_REASON_UNSAFE_DEFINITION, true
	case approvalsemantic.ActionFailureExecutionFailed:
		return runtimev1.ApprovalActionFailureReason_APPROVAL_ACTION_FAILURE_REASON_EXECUTION_FAILED, true
	case approvalsemantic.ActionFailureUnsupportedAction:
		return runtimev1.ApprovalActionFailureReason_APPROVAL_ACTION_FAILURE_REASON_UNSUPPORTED_ACTION, true
	default:
		return runtimev1.ApprovalActionFailureReason_APPROVAL_ACTION_FAILURE_REASON_UNSPECIFIED, false
	}
}

func fromWireApprovalActionFailureReason(value runtimev1.ApprovalActionFailureReason) (approvalsemantic.ActionFailureReason, bool) {
	switch value {
	case runtimev1.ApprovalActionFailureReason_APPROVAL_ACTION_FAILURE_REASON_UNAVAILABLE:
		return approvalsemantic.ActionFailureUnavailable, true
	case runtimev1.ApprovalActionFailureReason_APPROVAL_ACTION_FAILURE_REASON_INVALID_BINDING:
		return approvalsemantic.ActionFailureInvalidBinding, true
	case runtimev1.ApprovalActionFailureReason_APPROVAL_ACTION_FAILURE_REASON_UNSAFE_DEFINITION:
		return approvalsemantic.ActionFailureUnsafeDefinition, true
	case runtimev1.ApprovalActionFailureReason_APPROVAL_ACTION_FAILURE_REASON_EXECUTION_FAILED:
		return approvalsemantic.ActionFailureExecutionFailed, true
	case runtimev1.ApprovalActionFailureReason_APPROVAL_ACTION_FAILURE_REASON_UNSUPPORTED_ACTION:
		return approvalsemantic.ActionFailureUnsupportedAction, true
	default:
		return "", false
	}
}

func toWireApprovalReadKind(value approvalsemantic.ReadKind) (runtimev1.ApprovalReadKind, bool) {
	switch value {
	case approvalsemantic.ReadPendingForCaller:
		return runtimev1.ApprovalReadKind_APPROVAL_READ_KIND_PENDING_FOR_CALLER, true
	case approvalsemantic.ReadLatestForRecord:
		return runtimev1.ApprovalReadKind_APPROVAL_READ_KIND_LATEST_FOR_RECORD, true
	case approvalsemantic.ReadStepDisplayForRecord:
		return runtimev1.ApprovalReadKind_APPROVAL_READ_KIND_STEP_DISPLAY_FOR_RECORD, true
	default:
		return runtimev1.ApprovalReadKind_APPROVAL_READ_KIND_UNSPECIFIED, false
	}
}

func fromWireApprovalReadKind(value runtimev1.ApprovalReadKind) (approvalsemantic.ReadKind, bool) {
	switch value {
	case runtimev1.ApprovalReadKind_APPROVAL_READ_KIND_PENDING_FOR_CALLER:
		return approvalsemantic.ReadPendingForCaller, true
	case runtimev1.ApprovalReadKind_APPROVAL_READ_KIND_LATEST_FOR_RECORD:
		return approvalsemantic.ReadLatestForRecord, true
	case runtimev1.ApprovalReadKind_APPROVAL_READ_KIND_STEP_DISPLAY_FOR_RECORD:
		return approvalsemantic.ReadStepDisplayForRecord, true
	default:
		return "", false
	}
}

func toWireApprovalStepNoMatchBehavior(value approvalsemantic.StepNoMatchBehavior) (runtimev1.ApprovalStepNoMatchBehavior, bool) {
	switch value {
	case "":
		return runtimev1.ApprovalStepNoMatchBehavior_APPROVAL_STEP_NO_MATCH_BEHAVIOR_UNSPECIFIED, true
	case approvalsemantic.StepNoMatchNext:
		return runtimev1.ApprovalStepNoMatchBehavior_APPROVAL_STEP_NO_MATCH_BEHAVIOR_NEXT_STEP, true
	case approvalsemantic.StepNoMatchApprove:
		return runtimev1.ApprovalStepNoMatchBehavior_APPROVAL_STEP_NO_MATCH_BEHAVIOR_APPROVE, true
	case approvalsemantic.StepNoMatchReject:
		return runtimev1.ApprovalStepNoMatchBehavior_APPROVAL_STEP_NO_MATCH_BEHAVIOR_REJECT, true
	default:
		return runtimev1.ApprovalStepNoMatchBehavior_APPROVAL_STEP_NO_MATCH_BEHAVIOR_UNSPECIFIED, false
	}
}

func fromWireApprovalStepNoMatchBehavior(value runtimev1.ApprovalStepNoMatchBehavior) (approvalsemantic.StepNoMatchBehavior, bool) {
	switch value {
	case runtimev1.ApprovalStepNoMatchBehavior_APPROVAL_STEP_NO_MATCH_BEHAVIOR_UNSPECIFIED:
		return "", true
	case runtimev1.ApprovalStepNoMatchBehavior_APPROVAL_STEP_NO_MATCH_BEHAVIOR_NEXT_STEP:
		return approvalsemantic.StepNoMatchNext, true
	case runtimev1.ApprovalStepNoMatchBehavior_APPROVAL_STEP_NO_MATCH_BEHAVIOR_APPROVE:
		return approvalsemantic.StepNoMatchApprove, true
	case runtimev1.ApprovalStepNoMatchBehavior_APPROVAL_STEP_NO_MATCH_BEHAVIOR_REJECT:
		return approvalsemantic.StepNoMatchReject, true
	default:
		return "", false
	}
}
