package runtimeapi

import (
	"context"
	"errors"

	"github.com/nexuscrm/metadata/catalogsnapshot"
	"github.com/pingcap-inc/nexuscrm-api-host/runtimegrpc"
	catalogsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/catalog/consumerv1"
	commandsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/commandv1"
	recordsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recordsv1"
	"google.golang.org/grpc"
)

// CommandConsumerSelection binds one independently deployed Integration
// workload to the immutable command projection derived from its Catalog
// operation. Assembly pins the exact IntegrationBindingView for the admitted
// publication revision; this selection cannot author or widen command authority.
type CommandConsumerSelection struct {
	OrgID               string
	AppInstallationID   string
	WorkloadID          string
	RuntimeMetadataView *catalogsnapshot.RuntimeMetadataView
}

type commandConsumerAdmissionContextKey struct{}

// CommandConsumerAdmission closes consumer-only command admission without
// manufacturing an L1 HandlerBinding. SecurityAdmission authenticates the
// current workload/capability grant first; this owner then proves that the
// immutable command view and prepared Integration view share one Catalog
// revision before durable acceptance may run. Request admission does not
// rebuild that prepared Catalog authority.
type preparedCommandConsumer struct {
	selection CommandConsumerSelection
	current   catalogsemantic.IntegrationBindingView
}

// prepared captures one immutable consumer from its owning serving set.
type CommandConsumerAdmission struct {
	prepared func() *preparedCommandConsumer
}

func NewCommandConsumerAdmission(
	ctx context.Context,
	selection CommandConsumerSelection,
	catalogView CatalogConsumerViewEngine,
) (*CommandConsumerAdmission, error) {
	view := selection.RuntimeMetadataView
	if selection.OrgID == "" || selection.AppInstallationID == "" ||
		selection.WorkloadID == "" || catalogView == nil || view == nil ||
		view.OrgID() != selection.OrgID ||
		view.AppInstallationID() != selection.AppInstallationID ||
		view.CapabilityID() != commandsemantic.CapabilityName ||
		view.Profile() != catalogsnapshot.ProjectionCommandAcceptanceV1 {
		return nil, errors.New(
			"runtime command consumer admission: selection is incomplete",
		)
	}
	current, err := prepareIntegrationConsumerAuthority(
		ctx,
		integrationConsumerSelection{
			orgID: selection.OrgID, appInstallationID: selection.AppInstallationID,
			workloadID: selection.WorkloadID, capability: commandsemantic.CapabilityName,
			runtimeView: selection.RuntimeMetadataView,
		},
		catalogView,
	)
	if err != nil {
		return nil, err
	}
	snapshot := &preparedCommandConsumer{selection: selection, current: current}
	return &CommandConsumerAdmission{prepared: func() *preparedCommandConsumer { return snapshot }}, nil
}

func (a *CommandConsumerAdmission) UnaryServerInterceptor() grpc.UnaryServerInterceptor {
	return func(
		ctx context.Context,
		request any,
		_ *grpc.UnaryServerInfo,
		handler grpc.UnaryHandler,
	) (any, error) {
		capability, ok := runtimegrpc.Capability(ctx)
		if !ok {
			return nil, runtimegrpc.StatusError(ctx, &recordsemantic.Failure{
				Category: recordsemantic.FailureInternal,
			})
		}
		if capability != commandsemantic.CapabilityName {
			return handler(ctx, request)
		}
		admitted, err := a.bind(ctx)
		if err != nil {
			return nil, runtimegrpc.StatusError(ctx, err)
		}
		return handler(admitted, request)
	}
}

func (a *CommandConsumerAdmission) bind(ctx context.Context) (context.Context, error) {
	if a == nil || a.prepared == nil {
		return nil, &recordsemantic.Failure{
			Category: recordsemantic.FailureUnavailable,
		}
	}
	snapshot := a.prepared()
	if snapshot == nil {
		return nil, &recordsemantic.Failure{Category: recordsemantic.FailureUnavailable}
	}
	admitted, current, err := bindIntegrationConsumerAuthority(
		ctx,
		integrationConsumerSelection{
			orgID: snapshot.selection.OrgID, appInstallationID: snapshot.selection.AppInstallationID,
			workloadID: snapshot.selection.WorkloadID, capability: commandsemantic.CapabilityName,
			runtimeView: snapshot.selection.RuntimeMetadataView,
		},
		snapshot.current,
	)
	if err != nil {
		return nil, err
	}
	return context.WithValue(
		admitted,
		commandConsumerAdmissionContextKey{},
		current,
	), nil
}

func commandConsumerAuthorityFromAdmission(
	ctx context.Context,
	capability string,
) (catalogsemantic.IntegrationBindingView, bool) {
	if ctx == nil || capability != commandsemantic.CapabilityName {
		return catalogsemantic.IntegrationBindingView{}, false
	}
	current, admitted := ctx.Value(
		commandConsumerAdmissionContextKey{},
	).(catalogsemantic.IntegrationBindingView)
	scope, ok := runtimeExecutionScopeFromContext(ctx)
	return current, admitted && ok &&
		scope.capability == commandsemantic.CapabilityName &&
		scope.view != nil
}
