package records

import (
	"context"

	eventFeature "github.com/nexuscrm/events"
	appErrors "github.com/nexuscrm/kernel/pkg/errors"
	"github.com/nexuscrm/metadata"
	"github.com/nexuscrm/metadata/catalogsnapshot"
	"github.com/nexuscrm/persistence"
	"github.com/nexuscrm/shared/pkg/events"
)

// enqueueRecordEvent is the sole Records entry point for durable after-save
// events. Independent Runtime composition must persist both the opaque,
// immutable metadata binding and its queryable routing projection on every
// CRUD path; legacy composition deliberately adds neither.
func (ps *PersistenceService) enqueueRecordEvent(ctx context.Context, eventType events.EventType, payload eventFeature.RecordEventPayload) error {
	if ps == nil || ps.outbox == nil {
		return nil
	}
	enqueueCtx, err := ps.bindRuntimeRecordEvent(ctx)
	if err != nil {
		return err
	}
	return ps.outbox.EnqueueEvent(enqueueCtx, eventType, payload)
}

func (ps *PersistenceService) bindRuntimeRecordEvent(ctx context.Context) (context.Context, error) {
	if ps == nil || ps.metadata == nil || !ps.metadata.UsesRequestBoundRuntimeView() {
		return ctx, nil
	}
	view, ok := ps.metadata.BoundRuntimeMetadataView(ctx)
	if !ok {
		return nil, appErrors.NewInternalError("record event requires the request-bound Runtime metadata view", nil)
	}
	binding, err := catalogsnapshot.RuntimeWorkBindingFromView(view)
	if err != nil {
		return nil, appErrors.NewInternalError("derive record-event metadata binding", err)
	}
	encoded, err := catalogsnapshot.EncodeRuntimeWorkBinding(binding)
	if flowView, ok := metadata.RuntimeFlowWorkViewFromContext(ctx); ok {
		if flowView.Profile() != catalogsnapshot.ProjectionRecordMutationV1 {
			return nil, appErrors.NewInternalError("record event Flow work view has the wrong profile", nil)
		}
		flowBinding, bindErr := catalogsnapshot.RuntimeWorkBindingFromView(flowView)
		if bindErr != nil {
			return nil, appErrors.NewInternalError("derive record-event Flow work binding", bindErr)
		}
		encoded, err = catalogsnapshot.EncodeRuntimeWorkBindingSet(catalogsnapshot.RuntimeWorkBindingSet{
			Primary: binding, FlowWork: &flowBinding,
		})
	}
	if err != nil {
		return nil, appErrors.NewInternalError("encode record-event metadata binding", err)
	}
	ctx = eventFeature.WithDurableExecutionBinding(ctx, encoded)
	ctx, err = persistence.WithRuntimeWorkScope(ctx, persistence.RuntimeWorkScope{
		OrgID: binding.OrgID, AppInstallationID: binding.AppInstallationID, RuntimeCapabilityID: binding.RuntimeCapabilityID,
	})
	if err != nil {
		return nil, appErrors.NewInternalError("project record-event work scope", err)
	}
	return ctx, nil
}
