<?php

namespace Drupal\acquia_contenthub_translations\Libs\PullSyndication;

use Drupal\acquia_contenthub\Client\ClientFactory;
use Drupal\acquia_contenthub\Libs\Common\EnsureContentHubClientTrait;
use Drupal\acquia_contenthub\Libs\InterestList\InterestListStorageInterface;
use Drupal\acquia_contenthub\Libs\InterestList\InterestListTrait;
use Drupal\acquia_contenthub\Libs\Logging\ContentHubLoggerInterface;
use Drupal\acquia_contenthub\Settings\ContentHubConfigurationInterface;
use Drupal\acquia_contenthub_subscriber\EntityImportService;
use Drupal\acquia_contenthub_subscriber\Libs\PullSyndication\EntityUpsertAction;
use Drupal\acquia_contenthub_subscriber\SubscriberTracker;
use Drupal\acquia_contenthub_translations\TranslatableEntityFilter;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;
use Psr\Log\LoggerInterface;

/**
 * Action for upserting (create/update) translatable entities.
 *
 * Handles both entity creation and entity update operations
 * during pull syndication.
 *
 * @internal
 * @package Drupal\acquia_contenthub_translations\Libs\PullSyndication
 */
class TranslatableEntityUpsertAction extends EntityUpsertAction {

  use InterestListTrait;
  use EnsureContentHubClientTrait;

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

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

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

  /**
   * Constructs an TranslatableEntityUpsertAction object.
   *
   * @param \Drupal\acquia_contenthub_subscriber\SubscriberTracker $tracker
   *   Subscriber tracker.
   * @param \Drupal\acquia_contenthub\Settings\ContentHubConfigurationInterface $ch_configuration
   *   CH configuration.
   * @param \Drupal\acquia_contenthub\Libs\InterestList\InterestListStorageInterface $interest_list_storage
   *   Interest list storage.
   * @param \Drupal\acquia_contenthub\Libs\Logging\ContentHubLoggerInterface $ch_logger
   *   Content Hub logger service.
   * @param \Drupal\acquia_contenthub_subscriber\EntityImportService $entity_import_service
   *   Entity Import Service.
   * @param \Drupal\acquia_contenthub\Client\ClientFactory $client_factory
   *   The Content Hub Client factory service.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   Configuration factory.
   * @param \Psr\Log\LoggerInterface $translations_logger
   *   Translations logger.
   * @param \Drupal\acquia_contenthub_translations\TranslatableEntityFilter $translatable_entity_pruner
   *   The translatable entity filter service.
   */
  public function __construct(SubscriberTracker $tracker, ContentHubConfigurationInterface $ch_configuration, InterestListStorageInterface $interest_list_storage, ContentHubLoggerInterface $ch_logger, EntityImportService $entity_import_service, ClientFactory $client_factory, ConfigFactoryInterface $config_factory, LoggerInterface $translations_logger, TranslatableEntityFilter $translatable_entity_pruner) {
    parent::__construct($tracker, $ch_configuration, $interest_list_storage, $ch_logger, $entity_import_service, $client_factory);

    $this->translationConfig = $config_factory->get('acquia_contenthub_translations.settings');
    $this->logger = $translations_logger;
    $this->translatableEntityPruner = $translatable_entity_pruner;
  }

  /**
   * {@inheritdoc}
   */
  public function execute(array $queue_items): void {
    $client = $this->getClient();
    if (!$this->translationConfig->get('selective_language_import')) {
      return;
    }

    $webhook_uuid = $client->getSettings()->getWebhook('uuid');
    if (!$webhook_uuid) {
      $this->logger->error('Webhook UUID not found.');
      return;
    }

    $valid_queue_items = [];
    $entity_uuids = [];
    foreach ($queue_items as $queue_item) {
      if ($queue_item->getInitiator() === $client->getSettings()->getUuid()) {
        if ($queue_item->getCdfType() !== 'client') {
          $this->logger
            ->info('Service queue item will not be processed because its initiator is the existing client.
        Queue item data: {queue_item}', ['queue_item' => $queue_item]);
        }
        continue;
      }

      $uuid = $queue_item->getEntityUuid();
      if (!$this->isSupportedType($queue_item->getCdfType())) {
        $this->logger
          ->info('Entity with UUID {uuid} is not imported/updated because it has an unsupported type: {type}',
            ['uuid' => $uuid, 'type' => $queue_item->getCdfType()]
          );
        continue;
      }

      $valid_queue_items[$uuid] = $queue_item;
      $entity_uuids[] = $uuid;
    }

    if (empty($entity_uuids)) {
      return;
    }

    $untracked_entities = $this->tracker->getUntracked($entity_uuids) ?: [];
    $tracked_entities = empty($untracked_entities) ? $entity_uuids : array_diff($entity_uuids, $untracked_entities);
    $filtered_entity_uuids = empty($untracked_entities) ? $entity_uuids : $this->translatableEntityPruner->filterEntityUuidsBySubscriberLanguages($untracked_entities, $entity_uuids);
    $statuses = $this->tracker->getStatusesByUuids($tracked_entities);

    $entities_to_process = [];
    $auto_update_disabled_uuids = [];
    foreach ($filtered_entity_uuids as $uuid) {
      if (in_array($uuid, $tracked_entities, TRUE)) {
        $status = $statuses[$uuid] ?? NULL;
        if ($status === SubscriberTracker::AUTO_UPDATE_DISABLED) {
          $auto_update_disabled_uuids[] = $uuid;
          continue;
        }
      }
      $entities_to_process[] = $uuid;
    }
    if (!empty($auto_update_disabled_uuids)) {
      $this->logger->info('Entities not updated due to auto update disabled: {uuids}', ['uuids' => implode(', ', $auto_update_disabled_uuids)]);
    }

    if (empty($entities_to_process)) {
      return;
    }

    $this->logger->info('Attempting to import entities with UUIDs: {uuids}', ['uuids' => implode(', ', $entities_to_process)]);
    $this->processMultipleEntityUpserts($entities_to_process, $valid_queue_items);
  }

}
