package runtimeapi

import (
	"context"

	flowexecution "github.com/nexuscrm/backend/internal/runtimeflowexecution"
	"github.com/nexuscrm/shared/pkg/models"
)

const runtimeFlowMaxElementExecutions = flowexecution.MaxElementExecutions

type runtimeFlowMetadataView = flowexecution.MetadataView

type boundedAtomicFlowSelection struct {
	root                 *models.FlowVersion
	closureDigest        string
	maxElementExecutions uint64
	versions             []boundedAtomicFlowVersion
}

type boundedAtomicFlowVersion struct {
	definitionRef string
	version       *models.FlowVersion
}

func selectBoundedAtomicFlow(
	ctx context.Context,
	view runtimeFlowMetadataView,
	definitionRef string,
) (boundedAtomicFlowSelection, error) {
	selected, err := flowexecution.SelectSynchronousAPI(
		ctx,
		view,
		definitionRef,
	)
	return boundedAtomicFlowSelectionFromSelection(selected, err)
}

func selectBoundedAtomicFlowWithValidator(
	ctx context.Context,
	view runtimeFlowMetadataView,
	definitionRef string,
	validateAtomic flowexecution.AtomicValidator,
) (boundedAtomicFlowSelection, error) {
	selected, err := flowexecution.SelectSynchronousAPIWithValidator(
		ctx,
		view,
		definitionRef,
		validateAtomic,
	)
	return boundedAtomicFlowSelectionFromSelection(selected, err)
}

func selectCatalogActionFlow(
	ctx context.Context,
	view runtimeFlowMetadataView,
	definitionRef string,
	validateAtomic flowexecution.AtomicValidator,
) (boundedAtomicFlowSelection, error) {
	selected, err := flowexecution.SelectCatalogAction(
		ctx,
		view,
		definitionRef,
		validateAtomic,
	)
	return boundedAtomicFlowSelectionFromSelection(selected, err)
}

func boundedAtomicFlowSelectionFromSelection(
	selected flowexecution.Selection,
	err error,
) (boundedAtomicFlowSelection, error) {
	if err != nil {
		return boundedAtomicFlowSelection{}, err
	}
	versions := make([]boundedAtomicFlowVersion, 0, len(selected.Versions))
	for _, version := range selected.Versions {
		versions = append(versions, boundedAtomicFlowVersion{
			definitionRef: version.DefinitionRef,
			version:       version.Version,
		})
	}
	return boundedAtomicFlowSelection{
		root: selected.Root, closureDigest: selected.ClosureDigest,
		maxElementExecutions: selected.MaxElementExecutions,
		versions:             versions,
	}, nil
}
