package exec

import "fmt"

// allBuiltinActionDescriptors is the single typed descriptor source used by
// the public catalog and by governance validation. It deliberately performs no
// audit validation so typed audit contracts can resolve registered follow-ups
// without recursion.
func allBuiltinActionDescriptors() ([]actionDescriptor, error) {
	descriptors := make([]actionDescriptor, 0, len(builtinActionInventory))
	for _, describe := range []func() (actionDescriptor, error){
		func() (actionDescriptor, error) { return describe(workspaceListSpec) },
		func() (actionDescriptor, error) { return describe(projectListSpec) },
		func() (actionDescriptor, error) { return describe(projectCreateSpec) },
		func() (actionDescriptor, error) { return describe(projectDeleteSpec) },
		func() (actionDescriptor, error) { return describe(agentListSpec) },
		func() (actionDescriptor, error) { return describe(agentGetSpec) },
		func() (actionDescriptor, error) { return describe(agentStartSpec) },
		func() (actionDescriptor, error) { return describe(agentStopSpec) },
		func() (actionDescriptor, error) { return describe(agentRestartSpec) },
		func() (actionDescriptor, error) { return describe(agentCreateSpec) },
		func() (actionDescriptor, error) { return describe(agentUpdateSpec) },
		func() (actionDescriptor, error) { return describe(agentDeleteSpec) },
		func() (actionDescriptor, error) { return describe(agentDuplicateSpec) },
		func() (actionDescriptor, error) { return describe(teamListSpec) },
		func() (actionDescriptor, error) { return describe(teamGetSpec) },
		func() (actionDescriptor, error) { return describe(teamUpdateSpec) },
		func() (actionDescriptor, error) { return describe(channelListSpec) },
		func() (actionDescriptor, error) { return describe(channelGetSpec) },
		func() (actionDescriptor, error) { return describe(channelMembersSpec) },
		func() (actionDescriptor, error) { return describe(channelCreateSpec) },
		func() (actionDescriptor, error) { return describe(channelUpdateSpec) },
		func() (actionDescriptor, error) { return describe(channelAgentAddSpec) },
		func() (actionDescriptor, error) { return describe(channelAgentRemoveSpec) },
		func() (actionDescriptor, error) { return describe(reviewListSpec) },
		func() (actionDescriptor, error) { return describe(reviewAddSpec) },
		func() (actionDescriptor, error) { return describe(reviewDeleteSpec) },
		func() (actionDescriptor, error) { return describe(roleListSpec) },
		func() (actionDescriptor, error) { return describe(roleGetSpec) },
		func() (actionDescriptor, error) { return describe(roleRequestGetSpec) },
		func() (actionDescriptor, error) { return describe(roleCreateSpec) },
		func() (actionDescriptor, error) { return describe(roleUpdateSpec) },
		func() (actionDescriptor, error) { return describe(roleDeleteSpec) },
		func() (actionDescriptor, error) { return describe(roleApplySpec) },
		func() (actionDescriptor, error) { return describe(skillListSpec) },
		func() (actionDescriptor, error) { return describe(skillGetSpec) },
		func() (actionDescriptor, error) { return describe(skillCreateSpec) },
		func() (actionDescriptor, error) { return describe(skillUpdateSpec) },
		func() (actionDescriptor, error) { return describe(skillImportSpec) },
		func() (actionDescriptor, error) { return describe(skillDeleteSpec) },
		func() (actionDescriptor, error) { return describe(profileSetAvatarSpec) },
		func() (actionDescriptor, error) { return describe(taskCreateSpec) },
		func() (actionDescriptor, error) { return describe(taskGetSpec) },
		func() (actionDescriptor, error) { return describe(taskListSpec) },
		func() (actionDescriptor, error) { return describe(taskUpdateSpec) },
		func() (actionDescriptor, error) { return describe(taskClaimSpec) },
		func() (actionDescriptor, error) { return describe(taskUnclaimSpec) },
		func() (actionDescriptor, error) { return describe(taskCheckpointSpec) },
		func() (actionDescriptor, error) { return describe(taskDeleteSpec) },
		func() (actionDescriptor, error) { return describe(scheduledMessageListSpec) },
		func() (actionDescriptor, error) { return describe(scheduledMessageGetSpec) },
		func() (actionDescriptor, error) { return describe(scheduledMessageRunsSpec) },
		func() (actionDescriptor, error) { return describe(scheduledMessageValidateSpec) },
		func() (actionDescriptor, error) { return describe(scheduledMessageCreateSpec) },
		func() (actionDescriptor, error) { return describe(scheduledMessageUpdateSpec) },
		func() (actionDescriptor, error) { return describe(scheduledMessagePauseSpec) },
		func() (actionDescriptor, error) { return describe(scheduledMessageResumeSpec) },
		func() (actionDescriptor, error) { return describe(scheduledMessageDeleteSpec) },
		func() (actionDescriptor, error) { return describe(workflowPlanSpec) },
		func() (actionDescriptor, error) { return describe(workflowTriggerSpec) },
		func() (actionDescriptor, error) { return describe(workflowRunSpec) },
		func() (actionDescriptor, error) { return describe(workflowStepSpec) },
	} {
		descriptor, err := describe()
		if err != nil {
			return nil, err
		}
		descriptors = append(descriptors, descriptor)
	}
	return descriptors, nil
}

// DefaultCatalog builds the immutable model-visible action descriptor catalog.
func DefaultCatalog() (*Catalog, error) {
	descriptors, err := allBuiltinActionDescriptors()
	if err != nil {
		return nil, err
	}
	if err := validateBuiltinActionInventory(descriptors); err != nil {
		return nil, err
	}
	for _, descriptor := range descriptors {
		if len(descriptor.Examples) != 1 {
			return nil, fmt.Errorf(
				"exec: %s: exactly one canonical example required, got %d",
				descriptor.identity(),
				len(descriptor.Examples),
			)
		}
	}
	return newDescriptorCatalog(descriptors...)
}
