<?php

namespace Drupal\acquia_contenthub_subscriber\Commands;

use Drupal\acquia_contenthub\Client\ClientFactory;
use Drupal\acquia_contenthub\ContentHubConnectionManager;
use Drupal\acquia_contenthub\QueueInspectorInterface;
use Drupal\acquia_contenthub_subscriber\ContentHubImportQueueByFilter;
use Drupal\acquia_contenthub_subscriber\Traits\ImportQueueTrait;
use Drupal\Core\Queue\QueueWorkerManager;
use Drush\Commands\DrushCommands;
use Symfony\Component\Console\Helper\ProgressBar;

/**
 * Provides command to enqueue entities based on filters.
 *
 * @package Drupal\acquia_contenthub_subscriber\Commands
 */
class AcquiaContentHubSubscriberEnqueueEntitiesCommands extends DrushCommands {

  use ImportQueueTrait;

  /**
   * Content Hub import queue by filter service.
   *
   * @var \Drupal\acquia_contenthub_subscriber\ContentHubImportQueueByFilter
   */
  protected $importByFilter;

  /**
   * Client factory.
   *
   * @var \Drupal\acquia_contenthub\Client\ClientFactory
   */
  protected $clientFactory;

  /**
   * The queue worker.
   *
   * @var \Drupal\Core\Queue\QueueWorkerManager
   */
  protected $queueManager;

  /**
   * Subscriber queue inspector.
   *
   * @var \Drupal\acquia_contenthub\QueueInspectorInterface
   */
  protected QueueInspectorInterface $queueInspector;

  /**
   * AcquiaContentHubSubscriberEnqueueEntitiesCommands constructor.
   *
   * @param \Drupal\acquia_contenthub_subscriber\ContentHubImportQueueByFilter $import_by_filter
   *   Content Hub import queue by filter service.
   * @param \Drupal\acquia_contenthub\Client\ClientFactory $client_factory
   *   Acquia Content Hub Client factory.
   * @param \Drupal\Core\Queue\QueueWorkerManager $queue_manager
   *   The queue manager.
   * @param \Drupal\acquia_contenthub\QueueInspectorInterface $queue_inspector
   *   The subscriber queue inspector service.
   */
  public function __construct(ContentHubImportQueueByFilter $import_by_filter, ClientFactory $client_factory, QueueWorkerManager $queue_manager, QueueInspectorInterface $queue_inspector) {
    $this->importByFilter = $import_by_filter;
    $this->clientFactory = $client_factory;
    $this->queueManager = $queue_manager;
    $this->queueInspector = $queue_inspector;
  }

  /**
   * Subscriber enqueue entities based on filters.
   *
   * @option filter-uuids
   *   Comma-separated list of filter uuids.
   * @default filter-uuids
   *
   * @usage acquia:contenthub-enqueue-by-filters
   *   Creates queue items from the associated filters except default filter.
   * @usage acquia:contenthub-enqueue-by-filters --filter-uuids=00000aa0-a00a-000a-aa00-aaa000a0a0aa
   *   Creates queue items from passed filter uuid.
   * @usage acquia:contenthub-enqueue-by-filters --filter-uuids='00000aa0-a00a-000a-aa00-aaa000a0a0aa,00000bb0-b00b-000b-bb00-bbb000b0b0bb'
   *   Creates queue items from multiple filter uuids.
   *
   * @command acquia:contenthub-enqueue-by-filters
   * @aliases ach-enqueue-by-filters,ach-enfi
   *
   * @throws \Exception
   */
  public function enqueueEntities(): void {
    $uuids = $this->input->getOption('filter-uuids');
    $filter_uuids = explode(',', $uuids);
    $client = $this->clientFactory->getClient();
    $settings = $client->getSettings();

    if (empty($uuids)) {
      $webhook_uuid = $settings->getWebhook('uuid');
      if (empty($webhook_uuid)) {
        throw new \Exception('Webhook not found.');
      }

      $filters = $client->listFiltersForWebhook($webhook_uuid);
      $filter_uuids = $filters['data'] ?? [];
    }

    $uuids = [];
    $import_queue = $this->importByFilter->getQueue();
    foreach ($filter_uuids as $filter_uuid) {
      $filter_info = $client->getFilter($filter_uuid);
      if ($filter_info['data']['name'] === ContentHubConnectionManager::DEFAULT_FILTER . $settings->getName()) {
        continue;
      }
      $uuids[] = $filter_uuid;
    }

    $uuids = $this->filterByAlreadyEnqueuedItems($uuids, $this->queueInspector);
    if (empty($uuids)) {
      return;
    }
    foreach ($uuids as $filter_uuid) {
      $data = new \stdClass();
      $data->filter_uuid = $filter_uuid;
      $import_queue->createItem($data);
    }
    $this->processQueueItems();
  }

  /**
   * Processes queue items.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   */
  protected function processQueueItems(): void {
    $queue_worker = $this->queueManager->createInstance(ContentHubImportQueueByFilter::QUEUE_NAME);
    $import_queue = $this->importByFilter->getQueue();
    $symfony_progressbar = $this->initializeProgress($import_queue->numberOfItems());
    $symfony_progressbar->start();
    while ($import_queue->numberOfItems()) {
      /** @var \stdClass $item */
      $item = $import_queue->claimItem();
      $symfony_progressbar->advance();
      if (!$item) {
        break;
      }
      try {
        $queue_worker->processItem($item->data);
        $import_queue->deleteItem($item);
      }
      catch (\Exception $exception) {
        $import_queue->releaseItem($item);
      }
    }
    $symfony_progressbar->finish();
  }

  /**
   * Initializes the progress bar.
   *
   * @param int $source_count
   *   Maximum count of progress bar.
   *
   * @return \Symfony\Component\Console\Helper\ProgressBar
   *   The ProgressBar object.
   */
  protected function initializeProgress(int $source_count): ProgressBar {
    return new ProgressBar($this->output, $source_count);
  }

}
