<?php

namespace Drupal\acquia_contenthub_subscriber;

use Acquia\ContentHubClient\ContentHubClient;
use Drupal\acquia_contenthub\AcquiaContentHubQueueInspectorBase;
use Drupal\acquia_contenthub\Client\ClientFactory;
use Drupal\acquia_contenthub\Exception\ContentHubClientException;
use Drupal\Core\Database\Connection;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Queue\QueueFactory;
use Psr\Log\LoggerInterface;

/**
 * Provides subscriber import queue data.
 */
class SubscriberImportQueueInspector extends AcquiaContentHubQueueInspectorBase {

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

  /**
   * The logger channel.
   *
   * @var \Psr\Log\LoggerInterface
   */
  protected $logger;

  /**
   * The SubscriberImportQueueInspector constructor.
   *
   * @param \Drupal\Core\Queue\QueueFactory $queue_factory
   *   The queue factory.
   * @param \Drupal\Core\Database\Connection $database
   *   The database connection.
   * @param \Drupal\acquia_contenthub\Client\ClientFactory $client_factory
   *   The client factory.
   * @param \Psr\Log\LoggerInterface $logger
   *   The logger channel.
   */
  public function __construct(QueueFactory $queue_factory, Connection $database, ClientFactory $client_factory, LoggerInterface $logger) {
    parent::__construct($queue_factory, $database);

    $this->clientFactory = $client_factory;
    $this->logger = $logger;
  }

  /**
   * {@inheritDoc}
   */
  public function getQueueData(string $type = '', string $uuid = '', $limit = self::NO_LIMIT): array {
    $queue_data = parent::getQueueData($type, $uuid, $limit);

    $client = $this->getClient();
    $data = [];
    $limit = $limit > 0 ? $limit : self::NO_LIMIT;
    $uuids = [];

    foreach ($queue_data as $datum) {
      $uuids = array_merge($uuids, explode(', ', $datum['uuids']));
    }

    if (!$uuids) {
      return [];
    }
    $document = $client->getEntities($uuids);
    $missing_entities = array_diff_key(array_flip($uuids), $document->getEntities());
    $entities = $document->getEntities();

    // The queue can contain multiple of the same item. However, displaying them
    // would make sure that it provides the most accurate information.
    foreach ($uuids as $entity_uuid) {
      if (!isset($entities[$entity_uuid])) {
        continue;
      }
      $cdf = $entities[$entity_uuid];
      $entity['type'] = $cdf->getAttribute('entity_type')->getValue()[LanguageInterface::LANGCODE_NOT_SPECIFIED];
      $entity['uuid'] = $cdf->getUuid();
      if ($this->isMatchingData($entity, $type, $uuid)) {
        $data[] = $entity;
      }
    }
    if ($limit !== self::NO_LIMIT) {
      $data = array_slice($data, 0, $limit, TRUE);
    }

    if (!empty($missing_entities)) {
      $this->logger->info('Missing entities: {entities}',
        ['entities' => implode(', ', $missing_entities)]);
    }
    return $data;
  }

  /**
   * Gets the client or throws an exception when it's unavailable.
   *
   * @return \Acquia\ContentHubClient\ContentHubClient
   *   The ContentHubClient object or FALSE.
   *
   * @throws \Drupal\acquia_contenthub\Exception\ContentHubClientException
   */
  protected function getClient(): ContentHubClient {
    $client = $this->clientFactory->getClient();
    if (!($client instanceof ContentHubClient)) {
      throw new ContentHubClientException('Client is not properly configured.', ContentHubClientException::CLIENT_CONFIG_ERROR);
    }
    return $client;
  }

  /**
   * Provides name of the import queue.
   *
   * @return string
   *   The import queue name.
   */
  public function getQueueName(): string {
    return ContentHubImportQueue::QUEUE_NAME;
  }

}
