package runtimeapi

import (
	"context"
	"errors"

	"github.com/nexuscrm/persistence"
	"github.com/pingcap-inc/nexuscrm-api-host/runtimegrpc"
	applicationresultsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/applicationresultv1"
	commandsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/commandv1"
	commonsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/commonv1"
	"google.golang.org/grpc"
)

// ApplicationResultSelection is the immutable deployment selection for the
// one workload allowed to reconcile Runtime results for an AppInstallation.
// The Runtime-owned security projection, not this selection, remains the live
// grant, Org, epoch, and replica-lease authority.
type ApplicationResultSelection struct {
	AppInstallationID string
	WorkloadID        string
}

// ApplicationResultSecuritySource returns one durable security snapshot for
// an infrastructure-selected Runtime replica, AppInstallation, and
// host-authenticated workload. Implementations must not accept Org or epoch
// selectors from the request.
type ApplicationResultSecuritySource func(
	context.Context,
	string,
	string,
) (persistence.RuntimeSecurityIssuanceState, error)

type ApplicationResultAdmission struct {
	selection ApplicationResultSelection
	security  ApplicationResultSecuritySource
}

type applicationResultScopeContextKey struct{}

func NewApplicationResultAdmission(
	selection ApplicationResultSelection,
	security ApplicationResultSecuritySource,
) (*ApplicationResultAdmission, error) {
	if security == nil {
		return nil, errors.New(
			"runtime application result admission: security authority is required",
		)
	}
	// Reuse the persisted command-scope grammar so configuration cannot select
	// an identity that every result query would reject later.
	if _, err := (persistence.RuntimePlatformCommandTrustedScope{
		OrgID:               "runtime-application-result-selection",
		AppInstallationID:   selection.AppInstallationID,
		CallerWorkloadID:    selection.WorkloadID,
		RuntimeCapabilityID: commandsemantic.CapabilityName,
	}).Digest(); err != nil {
		return nil, errors.New(
			"runtime application result admission: selection is incomplete",
		)
	}
	return &ApplicationResultAdmission{
		selection: selection,
		security:  security,
	}, nil
}

func (a *ApplicationResultAdmission) 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, applicationResultFailure(
				commonsemantic.FailureInternal,
			))
		}
		if capability != applicationresultsemantic.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 *ApplicationResultAdmission) bind(
	ctx context.Context,
) (context.Context, error) {
	if a == nil || a.security == nil {
		return nil, applicationResultFailure(commonsemantic.FailureUnavailable)
	}
	trusted, ok := trustedWorkloadCallFromContext(ctx)
	if !ok {
		return nil, applicationResultFailure(commonsemantic.FailureUnavailable)
	}
	if trusted.callerWorkloadID != a.selection.WorkloadID ||
		trusted.capability != applicationresultsemantic.CapabilityName {
		return nil, applicationResultFailure(commonsemantic.FailureForbidden)
	}
	state, err := a.security(
		ctx,
		a.selection.AppInstallationID,
		a.selection.WorkloadID,
	)
	if err != nil {
		if ctxErr := ctx.Err(); ctxErr != nil {
			return nil, ctxErr
		}
		return nil, applicationResultFailure(commonsemantic.FailureUnavailable)
	}
	if err := ctx.Err(); err != nil {
		return nil, err
	}
	if !state.StateFound {
		return nil, applicationResultFailure(commonsemantic.FailureUnavailable)
	}
	if !state.BindingFound || !state.BindingActive ||
		state.OrgID != trusted.orgID ||
		!containsCapability(
			state.Capabilities,
			applicationresultsemantic.CapabilityName,
		) {
		return nil, applicationResultFailure(commonsemantic.FailureForbidden)
	}
	if state.SecurityEpoch == 0 || state.AuthorityNow.IsZero() {
		return nil, applicationResultFailure(commonsemantic.FailureInternal)
	}
	if trusted.securityEpoch != state.SecurityEpoch {
		return nil, staleSecurityFailure(
			state.SecurityEpoch,
			trusted.securityEpoch,
		)
	}
	if !state.LeaseFound || state.LeaseSecurityEpoch != state.SecurityEpoch ||
		state.LeaseExpiresAt.IsZero() ||
		!state.AuthorityNow.Before(state.LeaseExpiresAt) {
		return nil, staleSecurityFailure(
			state.SecurityEpoch,
			state.LeaseSecurityEpoch,
		)
	}
	scope := persistence.RuntimePlatformCommandTrustedScope{
		OrgID:               state.OrgID,
		AppInstallationID:   a.selection.AppInstallationID,
		CallerWorkloadID:    a.selection.WorkloadID,
		RuntimeCapabilityID: commandsemantic.CapabilityName,
	}
	if _, err := scope.Digest(); err != nil {
		return nil, applicationResultFailure(commonsemantic.FailureInternal)
	}
	return context.WithValue(
		ctx,
		applicationResultScopeContextKey{},
		scope,
	), nil
}

func applicationResultScopeFromAdmission(
	ctx context.Context,
) (persistence.RuntimePlatformCommandTrustedScope, bool) {
	if ctx == nil {
		return persistence.RuntimePlatformCommandTrustedScope{}, false
	}
	scope, ok := ctx.Value(applicationResultScopeContextKey{}).(persistence.RuntimePlatformCommandTrustedScope)
	if !ok || scope.RuntimeCapabilityID != commandsemantic.CapabilityName {
		return persistence.RuntimePlatformCommandTrustedScope{}, false
	}
	_, err := scope.Digest()
	return scope, err == nil
}

func applicationResultFailure(
	category commonsemantic.FailureCategory,
) error {
	return &applicationresultsemantic.Failure{Category: category}
}
