<?php

namespace Drupal\eb\Service;

use Drupal\eb\PluginInterfaces\OperationInterface;
use Drupal\eb\PluginManager\EbOperationPluginManager;

/**
 * Service for building operation instances.
 */
class OperationBuilder implements OperationBuilderInterface {

  /**
   * Constructor.
   *
   * @param \Drupal\eb\PluginManager\EbOperationPluginManager $operationManager
   *   The operation plugin manager.
   */
  public function __construct(
    protected EbOperationPluginManager $operationManager,
  ) {}

  /**
   * Build an operation from data.
   *
   * @param string $operation_id
   *   The operation plugin ID.
   * @param array<string, mixed> $data
   *   Operation data.
   *
   * @return \Drupal\eb\PluginInterfaces\OperationInterface
   *   The operation instance.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   *   If the operation plugin cannot be instantiated.
   */
  public function buildOperation(string $operation_id, array $data): OperationInterface {
    return $this->operationManager->createInstance($operation_id, [
      'data' => $data,
    ]);
  }

  /**
   * Build multiple operations from a batch of data.
   *
   * @param array<array<string, mixed>> $batch_data
   *   Array of operation data arrays.
   *
   * @return array<\Drupal\eb\PluginInterfaces\OperationInterface>
   *   Array of operation instances.
   */
  public function buildBatch(array $batch_data): array {
    $operations = [];

    foreach ($batch_data as $index => $data) {
      // Support both 'operation' and 'operation_type' for compatibility.
      $operation_id = $data['operation'] ?? $data['operation_type'] ?? NULL;

      if (!$operation_id) {
        continue;
      }

      try {
        $operations[$index] = $this->buildOperation($operation_id, $data);
      }
      catch (\Exception $e) {
        // Skip operations that fail to build.
        // Errors will be caught during validation.
      }
    }

    return $operations;
  }

  /**
   * Get available operation types.
   *
   * @return array<string, mixed>
   *   Array of operation definitions.
   */
  public function getAvailableOperations(): array {
    return $this->operationManager->getDefinitions();
  }

  /**
   * Check if an operation type exists.
   *
   * @param string $operation_id
   *   The operation plugin ID.
   *
   * @return bool
   *   TRUE if the operation exists.
   */
  public function operationExists(string $operation_id): bool {
    $definitions = $this->operationManager->getDefinitions();
    return isset($definitions[$operation_id]);
  }

}
