<?php

namespace PublishPress\FuturePro;

// phpcs:disable Generic.Files.LineLength.TooLong

use PublishPress\WordPressEDDLicense\Container as EDDContainer;
use PublishPress\WordPressEDDLicense\Services as EDDServices;
use PublishPress\WordPressEDDLicense\ServicesConfig as EDDServicesConfig;
use PublishPress\Future\Core\DI\ContainerInterface;
use PublishPress\Future\Core\DI\ServicesAbstract as FreeServicesAbstract;
use PublishPress\Future\Core\HooksAbstract as CoreHooksAbstract;
use PublishPress\Future\Modules\Workflows\Interfaces\StepProcessorInterface;
use PublishPress\FuturePro\Controllers\BaseDateController;
use PublishPress\FuturePro\Controllers\BlocksController;
use PublishPress\FuturePro\Controllers\CustomStatusesController;
use PublishPress\FuturePro\Controllers\EddIntegrationController;
use PublishPress\FuturePro\Controllers\MetadataMappingController;
use PublishPress\FuturePro\Controllers\SettingsController;
use PublishPress\FuturePro\Core\HooksAbstract;
use PublishPress\FuturePro\Core\PluginInitializator;
use PublishPress\FuturePro\Core\ServicesAbstract;
use PublishPress\FuturePro\Models\CustomStatusesModel;
use PublishPress\FuturePro\Models\SettingsModel;
use PublishPress\FuturePro\Modules\Notifications\DBTableSchemas\NotificationsSchema;
use PublishPress\FuturePro\Modules\Notifications\Migrations\V040600NotificationsSchema as MigrationsV040600NotificationsSchema;
use PublishPress\FuturePro\Modules\Workflows\DBTableSchemas\EventDrivenActionsLogSchema;
use PublishPress\FuturePro\Modules\Workflows\DBTableSchemas\EventDrivenActionsSchema;
use PublishPress\FuturePro\Modules\Workflows\Migrations\V040600EventDrivenActionsSchema as MigrationsV040600EventDrivenActionsSchema;
use PublishPress\FuturePro\Modules\Workflows\Migrations\V040600EventDrivenActionsLogSchema as MigrationsV040600EventDrivenActionsLogSchema;
use PublishPress\FuturePro\Modules\Workflows\Domain\Engine\InputValidators\UserQuery as InputValidatorsUserQuery;
use PublishPress\FuturePro\Modules\Workflows\Domain\Engine\JsonLogicEngine;
use PublishPress\FuturePro\Modules\Workflows\Domain\Engine\JsonLogicSqlPreprocessor;
use PublishPress\FuturePro\Modules\Workflows\Domain\Engine\WorkflowEngine;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Actions\Runners\AddPostMetaRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Actions\Runners\ConditionalRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Actions\Runners\DeletePostMetaRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Actions\Runners\DoActionRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Actions\Runners\UserInteractionRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Actions\Runners\QueryPostsRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Actions\Runners\DuplicatePostRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Actions\Runners\SendInSiteNotificationRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Actions\Runners\UpdatePostMetaRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Actions\Runners\UpdatePostRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Processors\InSiteNotification;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Triggers\Runners\OnAdminInitRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Triggers\Runners\OnCustomActionRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Triggers\Runners\OnInitRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Triggers\Runners\OnPostAuthorChangeRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Triggers\Runners\OnPostMetaChangeRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Triggers\Runners\OnPostRowActionRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Triggers\Runners\OnPostScheduleRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Triggers\Runners\OnPostStatusChangeRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Triggers\Runners\OnScheduleRunner;
use PublishPress\FuturePro\Modules\Workflows\Domain\Steps\Triggers\Runners\OnUserRoleChangeRunner;
use PublishPress\FuturePro\Modules\Workflows\Models\RecipientsModel;

// phpcs:enable Generic.Files.LineLength.TooLong

defined('ABSPATH') or die('No direct script access allowed.');

return [
    ServicesAbstract::PLUGIN_VERSION => PUBLISHPRESS_FUTURE_PRO_PLUGIN_VERSION,

    ServicesAbstract::PLUGIN_SLUG => PUBLISHPRESS_FUTURE_PRO_PLUGIN_SLUG,

    ServicesAbstract::PLUGIN_NAME => PUBLISHPRESS_FUTURE_PRO_PLUGIN_NAME,

    ServicesAbstract::PLUGIN_AUTHOR => PUBLISHPRESS_FUTURE_PRO_PLUGIN_AUTHOR,

    ServicesAbstract::PLUGIN_FILE => 'publishpress-future-pro/publishpress-future-pro.php',

    ServicesAbstract::BASE_PATH => PUBLISHPRESS_FUTURE_PRO_BASE_PATH,

    ServicesAbstract::TEMPLATE_PATH => PUBLISHPRESS_FUTURE_PRO_BASE_PATH . '/src/templates',

    ServicesAbstract::EDD_SITE_URL => PUBLISHPRESS_FUTURE_PRO_EDD_SITE_URL,

    ServicesAbstract::EDD_ITEM_ID => PUBLISHPRESS_FUTURE_PRO_EDD_ITEM_ID,

    ServicesAbstract::REST_API_V1_BASE_PATH => 'publishpress-future/v1',

    /**
     * @return string
     */
    ServicesAbstract::BASE_URL => static function (ContainerInterface $container) {
        return plugins_url('/', $container->get(ServicesAbstract::PLUGIN_FILE));
    },

    /**
     * @return string
     */
    ServicesAbstract::ASSETS_URL => static function (ContainerInterface $container) {
        return $container->get(ServicesAbstract::BASE_URL) . '/src/assets';
    },

    ServicesAbstract::MODULES => static function (ContainerInterface $container) {
        $modulesServicesList = [
            ServicesAbstract::MODULE_WORKFLOWS,
            ServicesAbstract::MODULE_WPFORMS,
            ServicesAbstract::MODULE_NOTIFICATIONS,
        ];

        $modules = [];
        foreach ($modulesServicesList as $service) {
            $modules[] = $container->get($service);
        }

        return $container->get(ServicesAbstract::HOOKS)->applyFilters(
            HooksAbstract::FILTER_MODULES_LIST,
            $modules
        );
    },

    /**
     * @return InitializableInterface[]
     */
    ServicesAbstract::CONTROLLERS => static function (ContainerInterface $container) {
        $controllerServicesList = [
            ServicesAbstract::CONTROLLER_CUSTOM_STATUSES,
            ServicesAbstract::CONTROLLER_SETTINGS,
            ServicesAbstract::CONTROLLER_EDD_INTEGRATION,
            ServicesAbstract::CONTROLLER_BASE_DATE,
            ServicesAbstract::CONTROLLER_BLOCKS,
            ServicesAbstract::CONTROLLER_METADATA_MAPPING,
        ];

        $controllers = [];
        foreach ($controllerServicesList as $service) {
            $controllers[] = $container->get($service);
        }

        return $container->get(ServicesAbstract::HOOKS)->applyFilters(
            HooksAbstract::FILTER_CONTROLLERS_LIST,
            $controllers
        );
    },

    /**
     * @return PluginInitializator
     */
    // FIXME: Could we simplify this and the above service to use the Free plugin initializator?
    ServicesAbstract::PLUGIN => static function (ContainerInterface $container) {
        return new PluginInitializator(
            $container->get(ServicesAbstract::CONTROLLERS),
            $container->get(ServicesAbstract::HOOKS),
            $container->get(ServicesAbstract::BASE_PATH),
            $container->get(ServicesAbstract::MODULES),
            $container->get(FreeServicesAbstract::LOGGER),
            $container->get(ServicesAbstract::PLUGIN_VERSION),
            $container->get(ServicesAbstract::MIGRATIONS_FACTORY)
        );
    },

    /**
     * @return ModuleInterface
     */
    ServicesAbstract::CONTROLLER_CUSTOM_STATUSES => static function (ContainerInterface $container) {
        return new CustomStatusesController(
            $container->get(ServicesAbstract::HOOKS),
            $container->get(ServicesAbstract::MODEL_CUSTOM_STATUSES),
            $container->get(ServicesAbstract::MODEL_SETTINGS),
            $container->get(FreeServicesAbstract::EXPIRABLE_POST_MODEL_FACTORY),
            $container->get(FreeServicesAbstract::EXPIRATION_ACTIONS_MODEL)
        );
    },

    /**
     * @return ModuleInterface
     */
    ServicesAbstract::CONTROLLER_SETTINGS => static function (ContainerInterface $container) {
        return new SettingsController(
            $container->get(ServicesAbstract::HOOKS),
            $container->get(ServicesAbstract::MODEL_SETTINGS),
            $container->get(ServicesAbstract::MODEL_CUSTOM_STATUSES),
            $container->get(ServicesAbstract::TEMPLATE_PATH),
            $container->get(ServicesAbstract::ASSETS_URL),
            $container->get(ServicesAbstract::EDD_CONTAINER),
            $container->get(ServicesAbstract::EDD_ITEM_ID),
            $container->get(ServicesAbstract::PLUGIN_VERSION)
        );
    },

    ServicesAbstract::CONTROLLER_EDD_INTEGRATION => static function (ContainerInterface $container) {
        return new EddIntegrationController(
            $container->get(ServicesAbstract::HOOKS),
            $container->get(ServicesAbstract::MODEL_SETTINGS),
            $container->get(ServicesAbstract::TEMPLATE_PATH),
            $container->get(ServicesAbstract::EDD_CONTAINER)
        );
    },

    ServicesAbstract::CONTROLLER_BASE_DATE => static function (ContainerInterface $container) {
        return new BaseDateController(
            $container->get(ServicesAbstract::HOOKS),
            $container->get(ServicesAbstract::MODEL_SETTINGS)
        );
    },

    ServicesAbstract::CONTROLLER_BLOCKS => static function (ContainerInterface $container) {
        return new BlocksController(
            $container->get(ServicesAbstract::HOOKS),
            $container->get(ServicesAbstract::ASSETS_URL),
            $container->get(FreeServicesAbstract::EXPIRABLE_POST_MODEL_FACTORY)
        );
    },

    ServicesAbstract::CONTROLLER_METADATA_MAPPING => static function (ContainerInterface $container) {
        return new MetadataMappingController(
            $container->get(ServicesAbstract::HOOKS),
            $container->get(ServicesAbstract::MODEL_SETTINGS),
            $container->get(FreeServicesAbstract::EXPIRABLE_POST_MODEL_FACTORY),
            $container->get(FreeServicesAbstract::EXPIRATION_SCHEDULER),
            $container->get(FreeServicesAbstract::POST_TYPE_DEFAULT_DATA_MODEL_FACTORY)
        );
    },

    ServicesAbstract::MODULE_WPFORMS => static function (ContainerInterface $container) {
        return new \PublishPress\FuturePro\Modules\Wpforms\Module(
            $container->get(ServicesAbstract::HOOKS)
        );
    },

    ServicesAbstract::MODULE_WORKFLOWS => static function (ContainerInterface $container) {
        return new \PublishPress\FuturePro\Modules\Workflows\Module(
            $container->get(ServicesAbstract::HOOKS),
            $container->get(ServicesAbstract::WORKFLOW_ENGINE),
            $container->get(FreeServicesAbstract::LOGGER),
            $container->get(FreeServicesAbstract::REQUEST),
            $container->get(FreeServicesAbstract::CURRENT_USER_MODEL_FACTORY)
        );
    },

    ServicesAbstract::MODULE_NOTIFICATIONS => static function (ContainerInterface $container) {
        return new \PublishPress\FuturePro\Modules\Notifications\Module(
            $container->get(ServicesAbstract::HOOKS),
            $container->get(FreeServicesAbstract::CURRENT_USER_MODEL_FACTORY),
            $container->get(ServicesAbstract::REST_API_V1_BASE_PATH),
            $container->get(ServicesAbstract::PLUGIN_VERSION)
        );
    },

    /**
     * @return \PublishPress\FuturePro\Models\CustomStatusesModel
     */
    ServicesAbstract::MODEL_CUSTOM_STATUSES => static function (ContainerInterface $container) {
        return new CustomStatusesModel();
    },

    ServicesAbstract::MODEL_SETTINGS => static function (ContainerInterface $container) {
        return new SettingsModel(
            $container->get(ServicesAbstract::OPTIONS),
            $container->get(ServicesAbstract::MODEL_CUSTOM_STATUSES),
            $container->get(FreeServicesAbstract::SETTINGS)
        );
    },

    ServicesAbstract::LICENSE_KEY => static function (ContainerInterface $container) {
        return $container->get(ServicesAbstract::MODEL_SETTINGS)->getLicenseKey();
    },

    ServicesAbstract::LICENSE_STATUS => static function (ContainerInterface $container) {
        return $container->get(ServicesAbstract::MODEL_SETTINGS)->getLicenseStatus();
    },

    ServicesAbstract::EDD_CONTAINER => static function (ContainerInterface $container) {
        $config = new EDDServicesConfig();
        $config->setApiUrl($container->get(ServicesAbstract::EDD_SITE_URL))
            ->setLicenseKey($container->get(ServicesAbstract::LICENSE_KEY))
            ->setLicenseStatus($container->get(ServicesAbstract::LICENSE_STATUS))
            ->setPluginVersion($container->get(ServicesAbstract::PLUGIN_VERSION))
            ->setEddItemId($container->get(ServicesAbstract::EDD_ITEM_ID))
            ->setPluginAuthor($container->get(ServicesAbstract::PLUGIN_AUTHOR))
            ->setPluginFile($container->get(ServicesAbstract::PLUGIN_FILE));

        $services = new EDDServices($config);

        $eddContainer = new EDDContainer();
        $eddContainer->register($services);

        return $eddContainer;
    },

    ServicesAbstract::MIGRATIONS_FACTORY => static function (ContainerInterface $container) {
        return function () use ($container) {
            $migrations = [
                new MigrationsV040600NotificationsSchema(
                    $container->get(ServicesAbstract::HOOKS),
                    $container->get(ServicesAbstract::DB_TABLE_WORKFLOW_NOTIFICATIONS_SCHEMA)
                ),
                new MigrationsV040600EventDrivenActionsSchema(
                    $container->get(ServicesAbstract::HOOKS),
                    $container->get(ServicesAbstract::DB_TABLE_WORKFLOW_EVENT_DRIVEN_ACTIONS_SCHEMA)
                ),
                new MigrationsV040600EventDrivenActionsLogSchema(
                    $container->get(ServicesAbstract::HOOKS),
                    $container->get(ServicesAbstract::DB_TABLE_WORKFLOW_EVENT_DRIVEN_ACTIONS_LOG_SCHEMA)
                ),
            ];

            $migrations = $container->get(ServicesAbstract::HOOKS)->applyFilters(
                CoreHooksAbstract::FILTER_MIGRATIONS,
                $migrations
            );

            return $migrations;
        };
    },

    ServicesAbstract::WORKFLOW_ENGINE => static function (ContainerInterface $container) {
        return new WorkflowEngine(
            $container->get(ServicesAbstract::HOOKS),
            $container->get(FreeServicesAbstract::WORKFLOW_ENGINE),
            $container->get(ServicesAbstract::STEP_RUNNER_FACTORY),
            $container->get(FreeServicesAbstract::LOGGER)
        );
    },

    ServicesAbstract::STEP_RUNNER_FACTORY => static function (ContainerInterface $container) {
        return function ($nodeName, $workflowExecutionId) use ($container) {
            $hooks = $container->get(ServicesAbstract::HOOKS);

            $executionContext = $container->get(FreeServicesAbstract::EXECUTION_CONTEXT_REGISTRY)
                ->getExecutionContext($workflowExecutionId);

            $generalStepProcessor = call_user_func(
                $container->get(FreeServicesAbstract::GENERAL_STEP_PROCESSOR_FACTORY),
                $workflowExecutionId
            );

            $logger = $container->get(FreeServicesAbstract::LOGGER);
            $settingsModel = $container->get(FreeServicesAbstract::SETTINGS);

            switch ($nodeName) {
                // Triggers
                case OnAdminInitRunner::getNodeTypeName():
                    if (! $settingsModel->getWorkflowExperimental()) {
                        return null;
                    }

                    return new OnAdminInitRunner(
                        $hooks,
                        $generalStepProcessor
                    );

                case OnInitRunner::getNodeTypeName():
                    if (! $settingsModel->getWorkflowExperimental()) {
                        return null;
                    }

                    return new OnInitRunner(
                        $hooks,
                        $generalStepProcessor
                    );

                case OnScheduleRunner::getNodeTypeName():
                    $cronStepProcessor = call_user_func(
                        $container->get(FreeServicesAbstract::CRON_STEP_PROCESSOR_FACTORY),
                        $generalStepProcessor,
                        $workflowExecutionId
                    );

                    return new OnScheduleRunner(
                        $cronStepProcessor,
                        $executionContext,
                        $hooks
                    );

                case OnPostStatusChangeRunner::getNodeTypeName():
                    $inputValidatorPostQuery = call_user_func(
                        $container->get(FreeServicesAbstract::INPUT_VALIDATOR_POST_QUERY_FACTORY),
                        $workflowExecutionId
                    );

                    return new OnPostStatusChangeRunner(
                        $hooks,
                        $generalStepProcessor,
                        $inputValidatorPostQuery,
                        $executionContext,
                        $logger,
                        $container->get(FreeServicesAbstract::EXPIRABLE_POST_MODEL_FACTORY),
                        $container->get(FreeServicesAbstract::POST_CACHE),
                        $container->get(FreeServicesAbstract::WORKFLOW_EXECUTION_SAFEGUARD)
                    );

                case OnPostScheduleRunner::getNodeTypeName():
                    $inputValidatorPostQuery = call_user_func(
                        $container->get(FreeServicesAbstract::INPUT_VALIDATOR_POST_QUERY_FACTORY),
                        $workflowExecutionId
                    );

                    return new OnPostScheduleRunner(
                        $hooks,
                        $generalStepProcessor,
                        $inputValidatorPostQuery,
                        $executionContext,
                        $logger,
                        $container->get(FreeServicesAbstract::EXPIRABLE_POST_MODEL_FACTORY),
                        $container->get(FreeServicesAbstract::POST_CACHE),
                        $container->get(FreeServicesAbstract::WORKFLOW_EXECUTION_SAFEGUARD)
                    );

                case OnPostMetaChangeRunner::getNodeTypeName():
                    $inputValidatorPostQuery = call_user_func(
                        $container->get(FreeServicesAbstract::INPUT_VALIDATOR_POST_QUERY_FACTORY),
                        $workflowExecutionId
                    );

                    return new OnPostMetaChangeRunner(
                        $hooks,
                        $generalStepProcessor,
                        $inputValidatorPostQuery,
                        $executionContext,
                        $logger,
                        $container->get(FreeServicesAbstract::EXPIRABLE_POST_MODEL_FACTORY),
                        $container->get(FreeServicesAbstract::WORKFLOW_EXECUTION_SAFEGUARD)
                    );

                case OnPostAuthorChangeRunner::getNodeTypeName():
                    $inputValidatorPostQuery = call_user_func(
                        $container->get(FreeServicesAbstract::INPUT_VALIDATOR_POST_QUERY_FACTORY),
                        $workflowExecutionId
                    );

                    return new OnPostAuthorChangeRunner(
                        $hooks,
                        $generalStepProcessor,
                        $inputValidatorPostQuery,
                        $executionContext,
                        $logger,
                        $container->get(FreeServicesAbstract::EXPIRABLE_POST_MODEL_FACTORY),
                        $container->get(FreeServicesAbstract::POST_CACHE),
                        $container->get(FreeServicesAbstract::WORKFLOW_EXECUTION_SAFEGUARD)
                    );

                case OnPostRowActionRunner::getNodeTypeName():
                    $inputValidatorPostQuery = call_user_func(
                        $container->get(FreeServicesAbstract::INPUT_VALIDATOR_POST_QUERY_FACTORY),
                        $workflowExecutionId
                    );

                    return new OnPostRowActionRunner(
                        $hooks,
                        $generalStepProcessor,
                        $inputValidatorPostQuery,
                        $executionContext,
                        $logger,
                        $container->get(FreeServicesAbstract::EXPIRABLE_POST_MODEL_FACTORY)
                    );

                case OnUserRoleChangeRunner::getNodeTypeName():
                    return new OnUserRoleChangeRunner(
                        $hooks,
                        $generalStepProcessor,
                        $container->get(ServicesAbstract::INPUT_VALIDATOR_USER_QUERY),
                        $executionContext,
                        $logger,
                        $container->get(FreeServicesAbstract::WORKFLOW_EXECUTION_SAFEGUARD)
                    );

                case OnCustomActionRunner::getNodeTypeName():
                    return new OnCustomActionRunner(
                        $hooks,
                        $generalStepProcessor,
                        $logger,
                        $executionContext
                    );

                // Actions
                case SendInSiteNotificationRunner::getNodeTypeName():
                    $inSiteNotificationProcessor = call_user_func(
                        $container->get(ServicesAbstract::IN_SITE_NOTIFICATION_PROCESSOR_FACTORY),
                        $generalStepProcessor,
                        $workflowExecutionId
                    );

                    return new SendInSiteNotificationRunner(
                        $inSiteNotificationProcessor
                    );

                case AddPostMetaRunner::getNodeTypeName():
                    $postStepProcessor = call_user_func(
                        $container->get(FreeServicesAbstract::POST_STEP_PROCESSOR_FACTORY),
                        $generalStepProcessor,
                        $workflowExecutionId
                    );

                    return new AddPostMetaRunner(
                        $hooks,
                        $postStepProcessor,
                        $container->get(FreeServicesAbstract::EXPIRABLE_POST_MODEL_FACTORY),
                        $executionContext,
                        $logger
                    );

                case DeletePostMetaRunner::getNodeTypeName():
                    $postStepProcessor = call_user_func(
                        $container->get(FreeServicesAbstract::POST_STEP_PROCESSOR_FACTORY),
                        $generalStepProcessor,
                        $workflowExecutionId
                    );

                    return new DeletePostMetaRunner(
                        $postStepProcessor,
                        $container->get(FreeServicesAbstract::EXPIRABLE_POST_MODEL_FACTORY),
                        $executionContext,
                    );

                case UpdatePostMetaRunner::getNodeTypeName():
                    $postStepProcessor = call_user_func(
                        $container->get(FreeServicesAbstract::POST_STEP_PROCESSOR_FACTORY),
                        $generalStepProcessor,
                        $workflowExecutionId
                    );

                    return new UpdatePostMetaRunner(
                        $hooks,
                        $postStepProcessor,
                        $container->get(FreeServicesAbstract::EXPIRABLE_POST_MODEL_FACTORY),
                        $executionContext,
                        $logger
                    );

                case UpdatePostRunner::getNodeTypeName():
                    $postStepProcessor = call_user_func(
                        $container->get(FreeServicesAbstract::POST_STEP_PROCESSOR_FACTORY),
                        $generalStepProcessor,
                        $workflowExecutionId
                    );

                    return new UpdatePostRunner(
                        $hooks,
                        $postStepProcessor,
                        $container->get(FreeServicesAbstract::EXPIRABLE_POST_MODEL_FACTORY),
                        $executionContext,
                        $logger
                    );

                case DuplicatePostRunner::getNodeTypeName():
                    $postStepProcessor = call_user_func(
                        $container->get(FreeServicesAbstract::POST_STEP_PROCESSOR_FACTORY),
                        $generalStepProcessor,
                        $workflowExecutionId
                    );

                    return new DuplicatePostRunner(
                        $postStepProcessor,
                        $executionContext,
                        $logger,
                        $container->get(FreeServicesAbstract::WORKFLOW_EXECUTION_SAFEGUARD)
                    );

                // Advanced
                case QueryPostsRunner::getNodeTypeName():
                    return new QueryPostsRunner(
                        $generalStepProcessor,
                        $executionContext,
                        $logger,
                        $container->get(ServicesAbstract::JSON_LOGIC_SQL_PREPROCESSOR)
                    );

                case ConditionalRunner::getNodeTypeName():
                    $jsonLogicEngine = call_user_func(
                        $container->get(FreeServicesAbstract::JSON_LOGIC_ENGINE_FACTORY),
                        $executionContext
                    );

                    return new ConditionalRunner(
                        $generalStepProcessor,
                        $executionContext,
                        $jsonLogicEngine,
                        $logger
                    );

                case DoActionRunner::getNodeTypeName():
                    return new DoActionRunner(
                        $generalStepProcessor,
                        $executionContext,
                        $logger,
                        $hooks
                    );

                case UserInteractionRunner::getNodeTypeName():
                    $inSiteNotificationProcessor = call_user_func(
                        $container->get(ServicesAbstract::IN_SITE_NOTIFICATION_PROCESSOR_FACTORY),
                        $generalStepProcessor,
                        $workflowExecutionId
                    );

                    return new UserInteractionRunner(
                        $inSiteNotificationProcessor,
                        $executionContext,
                        $logger,
                        $hooks,
                        $container->get(ServicesAbstract::RECIPIENTS_MODEL)
                    );
            }

            return null;
        };
    },

    /**
     * @deprecated 4.4.0 Use the service available in the free version instead.
     */
    ServicesAbstract::JSON_LOGIC_ENGINE => static function (ContainerInterface $container) {
        return new JsonLogicEngine();
    },

    ServicesAbstract::INPUT_VALIDATOR_USER_QUERY => static function (ContainerInterface $container) {
        return new InputValidatorsUserQuery();
    },

    ServicesAbstract::JSON_LOGIC_SQL_PREPROCESSOR => static function (ContainerInterface $container) {
        return new JsonLogicSqlPreprocessor();
    },

    ServicesAbstract::DB_TABLE_WORKFLOW_NOTIFICATIONS_SCHEMA => static function (ContainerInterface $container) {
        $schemaHandlerFactory = $container->get(FreeServicesAbstract::DB_TABLE_SCHEMA_HANDLER_FACTORY);
        $schemaHandler = $schemaHandlerFactory();

        return new NotificationsSchema(
            $schemaHandler,
            'ppfuture_notifications'
        );
    },

    ServicesAbstract::DB_TABLE_WORKFLOW_EVENT_DRIVEN_ACTIONS_SCHEMA => static function (ContainerInterface $container) {
        $schemaHandlerFactory = $container->get(FreeServicesAbstract::DB_TABLE_SCHEMA_HANDLER_FACTORY);
        $schemaHandler = $schemaHandlerFactory();

        return new EventDrivenActionsSchema(
            $schemaHandler,
            'ppfuture_event_driven_actions'
        );
    },

    ServicesAbstract::DB_TABLE_WORKFLOW_EVENT_DRIVEN_ACTIONS_LOG_SCHEMA => static function (
        ContainerInterface $container
    ) {
        $schemaHandlerFactory = $container->get(FreeServicesAbstract::DB_TABLE_SCHEMA_HANDLER_FACTORY);
        $schemaHandler = $schemaHandlerFactory();

        return new EventDrivenActionsLogSchema(
            $schemaHandler,
            'ppfuture_event_driven_actions_log'
        );
    },

    ServicesAbstract::RECIPIENTS_MODEL => static function (ContainerInterface $container) {
        return new RecipientsModel();
    },

    ServicesAbstract::IN_SITE_NOTIFICATION_PROCESSOR_FACTORY =>
    static function (ContainerInterface $container): \Closure {
        return static function (
            StepProcessorInterface $generalProcessor,
            string $workflowExecutionId
        ) use ($container): StepProcessorInterface {
            $executionContext = $container->get(FreeServicesAbstract::EXECUTION_CONTEXT_REGISTRY)
                ->getExecutionContext($workflowExecutionId);

            return new InSiteNotification(
                $container->get(ServicesAbstract::HOOKS),
                $generalProcessor,
                $container->get(FreeServicesAbstract::LOGGER),
                $executionContext,
                $container->get(ServicesAbstract::RECIPIENTS_MODEL)
            );
        };
    },
];
