<?php

namespace Drupal\acquia_contenthub_translations\EventSubscriber\HandleWebhook;

use Acquia\ContentHubClient\Syndication\SyndicationStatus;
use Drupal\acquia_contenthub\Client\CdfMetricsManager;
use Drupal\acquia_contenthub\Event\HandleWebhookEvent;
use Drupal\acquia_contenthub\Libs\InterestList\InterestListStorageInterface;
use Drupal\acquia_contenthub\Libs\InterestList\InterestListTrait;
use Drupal\acquia_contenthub\QueueInspectorInterface;
use Drupal\acquia_contenthub\Settings\ContentHubConfigurationInterface;
use Drupal\acquia_contenthub_subscriber\EventSubscriber\HandleWebhook\ImportUpdateAssets;
use Drupal\acquia_contenthub_subscriber\SubscriberTracker;
use Drupal\acquia_contenthub_translations\TranslatableEntityFilter;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Queue\QueueFactory;
use Psr\Log\LoggerInterface;

/**
 * Imports and updates assets based on available languages.
 *
 * @package Drupal\acquia_contenthub_translations\EventSubscriber\HandleWebhook
 */
class ImportUpdateTranslatableAssets extends ImportUpdateAssets {

  use InterestListTrait;

  /**
   * The queue object.
   *
   * @var \Drupal\Core\Queue\QueueInterface
   */
  protected $queue;

  /**
   * The subscription tracker.
   *
   * @var \Drupal\acquia_contenthub_subscriber\SubscriberTracker
   */
  protected $tracker;

  /**
   * Cdf Metrics Manager.
   *
   * @var \Drupal\acquia_contenthub\Client\CdfMetricsManager
   */
  protected $cdfMetricsManager;

  /**
   * Content Hub translations config.
   *
   * @var \Drupal\Core\Config\ImmutableConfig
   */
  protected $translationConfig;

  /**
   * The Subscriber Import Queue Inspector.
   *
   * @var \Drupal\acquia_contenthub\QueueInspectorInterface
   */
  protected QueueInspectorInterface $queueInspector;

  /**
   * The translatable entity filter service.
   *
   * @var \Drupal\acquia_contenthub_translations\TranslatableEntityFilter
   */
  protected TranslatableEntityFilter $translatableEntityPruner;

  /**
   * ImportUpdateAssets constructor.
   *
   * @param \Drupal\Core\Queue\QueueFactory $queue
   *   Queue factory.
   * @param \Drupal\acquia_contenthub_subscriber\SubscriberTracker $tracker
   *   Subscriber tracker.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   Configuration factory.
   * @param \Drupal\acquia_contenthub\Client\CdfMetricsManager $cdf_metrics_manager
   *   Cdf metrics manager.
   * @param \Psr\Log\LoggerInterface $translations_logger
   *   Translations logger.
   * @param \Drupal\acquia_contenthub\Settings\ContentHubConfigurationInterface $ach_configurations
   *   Acquia contenthub configurations.
   * @param \Drupal\acquia_contenthub\QueueInspectorInterface $queue_inspector
   *   Queue inspector.
   * @param \Drupal\acquia_contenthub\Libs\InterestList\InterestListStorageInterface $interest_list_storage
   *   Interest list storage.
   * @param \Drupal\acquia_contenthub_translations\TranslatableEntityFilter $translatable_entity_pruner
   *   The translatable entity filter service.
   */
  public function __construct(QueueFactory $queue, SubscriberTracker $tracker, ConfigFactoryInterface $config_factory, CdfMetricsManager $cdf_metrics_manager, LoggerInterface $translations_logger, ContentHubConfigurationInterface $ach_configurations, QueueInspectorInterface $queue_inspector, InterestListStorageInterface $interest_list_storage, TranslatableEntityFilter $translatable_entity_pruner) {
    parent::__construct($queue, $tracker, $translations_logger, $ach_configurations, $cdf_metrics_manager, $queue_inspector, $interest_list_storage);
    $this->queue = $queue->get('acquia_contenthub_subscriber_import');
    $this->tracker = $tracker;
    $this->logger = $translations_logger;
    $this->translationConfig = $config_factory->get('acquia_contenthub_translations.settings');
    $this->cdfMetricsManager = $cdf_metrics_manager;
    $this->queueInspector = $queue_inspector;
    $this->translatableEntityPruner = $translatable_entity_pruner;
  }

  /**
   * Handles webhook events.
   *
   * @param \Drupal\acquia_contenthub\Event\HandleWebhookEvent $event
   *   The HandleWebhookEvent object.
   *
   * @throws \Exception
   */
  public function onHandleWebhook(HandleWebhookEvent $event): void {
    if (!$this->translationConfig->get('selective_language_import')) {
      parent::onHandleWebhook($event);
      return;
    }
    $payload = $event->getPayload();
    $this->client = $event->getClient();

    // Nothing to do or log here.
    if (!isset($payload['crud']) || $payload['crud'] !== 'update' || $event->isWebhookV2()) {
      return;
    }

    if ($payload['status'] !== 'successful' || !isset($payload['assets']) || !count($payload['assets'])) {
      $this->logger
        ->info('Payload will not be processed because it is not successful or it does not have assets.
        Payload data: {payload}', ['payload' => print_r($payload, TRUE)]);
      return;
    }

    if ($payload['initiator'] === $this->client->getSettings()->getUuid()) {
      // Only log if we're trying to update something other than client objects.
      if ($payload['assets'][0]['type'] !== 'client') {
        $this->logger
          ->info('Payload will not be processed because its initiator is the existing client.
        Payload data: {payload}', ['payload' => print_r($payload, TRUE)]);
      }

      return;
    }

    $uuids = [];
    $types = ['drupal8_content_entity', 'drupal8_config_entity'];
    foreach ($payload['assets'] as $asset) {
      $uuid = $asset['uuid'];
      $type = $asset['type'];
      if (!in_array($type, $types, FALSE)) {
        $this->logger
          ->info('Entity with UUID {uuid} was not added to the import queue because it has an unsupported type: {type}',
            ['uuid' => $uuid, 'type' => $type]
          );
        continue;
      }
      $uuids[] = $uuid;
    }
    if (empty($uuids)) {
      return;
    }

    $uuids_to_queue = [];
    $values = [];
    $untracked_uuids = $this->tracker->getUntracked($uuids);
    $tracked_uuids = empty($untracked_uuids) ? $uuids : array_diff($uuids, $untracked_uuids);
    $uuids = empty($untracked_uuids) ? $uuids : $this->translatableEntityPruner->filterEntityUuidsBySubscriberLanguages($untracked_uuids, $uuids);
    foreach ($uuids as $uuid) {
      if (in_array($uuid, $tracked_uuids, TRUE)) {
        $status = $this->tracker->getStatusByUuid($uuid);
        if ($status === SubscriberTracker::AUTO_UPDATE_DISABLED) {
          $this->logger
            ->info('Entity with UUID {uuid} was not added to the import queue because it has auto update disabled.',
              ['uuid' => $uuid]
            );
          continue;
        }
      }
      $uuids_to_queue[] = $uuid;
      $values[] = ['entity_uuid' => $uuid, 'hash' => ''];
      $this->logger
        ->info('Attempting to add entity with UUID {uuid} to the import queue.',
          ['uuid' => $uuid]
        );
    }
    if (!empty($values)) {
      $this->tracker->queueMultiple($values);
    }
    $uuids_to_queue = $this->filterByAlreadyEnqueuedItems($uuids_to_queue, $this->queueInspector);
    if (empty($uuids_to_queue)) {
      return;
    }
    $item = new \stdClass();
    $item->uuids = implode(', ', $uuids_to_queue);
    $queue_id = $this->queue->createItem($item);
    if (empty($queue_id)) {
      return;
    }
    $this->tracker->setQueueItemByUuids($uuids_to_queue, $queue_id);
    $this->logger
      ->info('Entities with UUIDs {uuids} added to the import queue and to the tracking table.',
        ['uuids' => print_r($uuids, TRUE)]);
    $send_contenthub_updates = $this->achConfigurations->getContentHubConfig()->shouldSendContentHubUpdates();
    if ($send_contenthub_updates) {
      $webhook_uuid = $this->client->getSettings()->getWebhook('uuid');
      if ($this->isWebhookLandingManual($payload)) {
        $disabled_entities = $this->interestListStorage->getInterestList($webhook_uuid, 'subscriber', [
          'uuids' => $uuids_to_queue,
          'disable_syndication' => TRUE,
        ]);
        $uuids_to_queue = $this->filterDisabledEntities($uuids_to_queue, array_keys($disabled_entities));
      }
      $this->client->addEntitiesToInterestListBySiteRole(
        $webhook_uuid,
        'subscriber',
        $this->buildInterestList(
          $uuids_to_queue,
          SyndicationStatus::QUEUED_TO_IMPORT,
          $payload[self::REASON_ATTRIBUTE] ?? 'manual'
        )
      );
    }

    $this->cdfMetricsManager->sendClientCdfUpdates();
    // Essential so that subscriber module doesn't override this logic.
    $event->stopPropagation();
  }

}
