<?php

declare(strict_types=1);

namespace Drupal\flowdrop\Plugin\FlowDropNodeProcessor;

use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginBase;
use Drupal\flowdrop\DTO\ValidationResult;

/**
 * Abstract base class for FlowDropNode plugins.
 *
 * This class provides common functionality for FlowDropNode plugins and
 * implements default behavior for the FlowDropNodeProcessorInterface methods.
 *
 * All plugins must implement:
 * - getParameterSchema(): Define the data contract (types, defaults,
 *   constraints)
 * - process(ParameterBagInterface $params): The main processing logic
 *
 * LOGGING POLICY:
 * - Routine logging (start, complete, input/output) is handled by the
 *   orchestration layer via ExecutionLogger.
 * - Processors should ONLY log exceptional events worth flagging:
 *   - External service retries/failures
 *   - Fallback usage
 *   - Rate limits
 *   - Unexpected data shapes
 * - For such exceptional logging, inject LoggerChannelFactoryInterface
 *   in the concrete processor that needs it.
 *
 * Note: UI/workflow behavior (connectable, configurable, required) is
 * controlled entirely by the config entity, not by the plugin schema.
 *
 * RESERVED PARAMETER NAMES: Do not use 'dynamicInputs' or 'dynamicOutputs'
 * as parameter names in getParameterSchema() unless implementing dynamic
 * port support via DynamicPortTrait. These names are intercepted by the API
 * layer and routed to configSchema regardless of entity configuration.
 *
 * @see \Drupal\flowdrop\Plugin\FlowDropNodeProcessor\DynamicPortTrait
 * @see \Drupal\flowdrop_node_processor\Plugin\FlowDropNodeProcessor\DataMapper
 * @see docs/development/reserved-names.md
 *
 * @see \Drupal\flowdrop\Plugin\FlowDropNodeProcessor\FlowDropNodeProcessorInterface
 * @see \Drupal\flowdrop_runtime\Service\Logging\ExecutionLoggerInterface
 * @see docs/development/flowdrop-node-processor.md
 *
 * @api
 */
abstract class AbstractFlowDropNodeProcessor extends PluginBase implements FlowDropNodeProcessorInterface, ContainerFactoryPluginInterface {

  /**
   * {@inheritdoc}
   */
  public function getOutputSchema(): array {
    return [
      "type" => "object",
      "properties" => [
        "data" => [
          "type" => "mixed",
          "description" => "Output data from the node",
        ],
      ],
    ];
  }

  /**
   * {@inheritdoc}
   *
   * Default implementation returns an empty schema.
   * Subclasses should override this to define their parameters.
   */
  public function getParameterSchema(): array {
    return [
      "type" => "object",
      "properties" => [],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getId(): string {
    return $this->pluginDefinition["id"] ?? $this->getPluginId();
  }

  /**
   * {@inheritdoc}
   */
  public function getName(): string {
    return $this->pluginDefinition["label"] ?? $this->getPluginId();
  }

  /**
   * {@inheritdoc}
   */
  public function getDescription(): string {
    return $this->pluginDefinition["description"] ?? "";
  }

  /**
   * {@inheritdoc}
   */
  public function getVersion(): string {
    return $this->pluginDefinition["version"] ?? "1.0.0";
  }

  /**
   * {@inheritdoc}
   */
  public function validateParams(array $params): ValidationResult {
    // Default implementation - always valid.
    // Subclasses can override for custom validation.
    return ValidationResult::success();
  }

}
