<?php

namespace Drupal\acquia_contenthub_subscriber\Libs\InterestList;

use Acquia\ContentHubClient\ContentHubClient;
use Drupal\acquia_contenthub\Client\ClientFactory;
use Drupal\acquia_contenthub\Exception\ContentHubClientException;
use Drupal\acquia_contenthub\Exception\ContentHubException;
use Drupal\acquia_contenthub\Libs\Traits\ResponseCheckerTrait;
use Drupal\acquia_contenthub_subscriber\SubscriberTracker;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;

/**
 * Interest list handler updates disabled entities.
 *
 * In subscriber tracking table in interest list.
 */
class InterestListHandler {

  use ResponseCheckerTrait;

  /**
   * Subscriber tracker.
   *
   * @var \Drupal\acquia_contenthub_subscriber\SubscriberTracker
   */
  protected SubscriberTracker $subscriberTracker;

  /**
   * Content Hub client.
   *
   * @var \Acquia\ContentHubClient\ContentHubClient|bool
   */
  protected $client;

  /**
   * Entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected EntityTypeManagerInterface $entityTypeManager;

  /**
   * Content Hub subscriber logger.
   *
   * @var \Psr\Log\LoggerInterface
   */
  protected LoggerInterface $chLogger;

  /**
   * InterestListHandler constructor.
   *
   * @param \Drupal\acquia_contenthub_subscriber\SubscriberTracker $subscriberTracker
   *   Subscriber tracker.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   Entity type manager.
   * @param \Drupal\acquia_contenthub\Client\ClientFactory $client_factory
   *   Client factory.
   * @param \Psr\Log\LoggerInterface $ch_logger
   *   Content Hub subscriber logger.
   *
   * @throws \Exception
   */
  public function __construct(SubscriberTracker $subscriberTracker, EntityTypeManagerInterface $entity_type_manager, ClientFactory $client_factory, LoggerInterface $ch_logger) {
    $this->subscriberTracker = $subscriberTracker;
    $this->entityTypeManager = $entity_type_manager;
    $this->client = $client_factory->getClient();
    $this->chLogger = $ch_logger;
  }

  /**
   * Updates disabled entities in Interest list.
   *
   * Entities that are marked as AUTO_UPDATE_DISABLED in Subscriber tracker
   * will be marked true for disable_syndication in interest list.
   *
   * @throws \Drupal\acquia_contenthub\Exception\ContentHubClientException
   * @throws \Drupal\acquia_contenthub\Exception\ContentHubException
   */
  public function updateDisabledEntitiesOnInterestList(): void {
    if (!$this->client instanceof ContentHubClient) {
      throw new ContentHubClientException('Error trying to connect to the Content Hub. Make sure this site is registered to Content hub.');
    }
    $settings = $this->client->getSettings();
    $webhook_uuid = $settings ? $settings->getWebhook('uuid') : '';
    if (!$webhook_uuid) {
      throw new ContentHubException('Webhook not available, unable to fetch interest list.');
    }
    $content_entities = $this->getDisabledContentEntitiesFromTrackingTable();

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

    $resp = $this->updateInterestList(array_keys($content_entities), $webhook_uuid, TRUE);
    if ($this->isSuccessful($resp)) {
      $this->chLogger->info(
        'All the content entities ({entities}) that were set to AUTO_UPDATE_DISABLED have been marked as disabled for syndication in interest list.',
        ['entities' => implode(', ', array_values($content_entities))]
      );
    }
    else {
      $this->chLogger->error('Could not update interest list for disabled entities. Error code: {error_code}. Error: {error}',
      [
        'error_code' => $resp->getStatusCode(),
        'error' => $resp->getBody(),
      ]
      );
    }
  }

  /**
   * Updates interest list.
   *
   * @param array $uuids
   *   List of uuids to be updated.
   * @param string $webhook_uuid
   *   Webhook uuid.
   * @param bool $disable_syndication
   *   Enable/disable syndication flag.
   *
   * @return \Psr\Http\Message\ResponseInterface
   *   Response object.
   */
  public function updateInterestList(array $uuids, string $webhook_uuid, bool $disable_syndication): ResponseInterface {
    $interest_list = [
      'uuids' => $uuids,
      'disable_syndication' => $disable_syndication,
    ];
    return $this->client->updateInterestListBySiteRole(
      $webhook_uuid,
      'subscriber',
      $interest_list
    );
  }

  /**
   * Returns disabled entities from Subscriber tracker.
   *
   * @return array
   *   Array of content and config entities separated.
   */
  public function getDisabledContentEntitiesFromTrackingTable(): array {
    $config_entities = $content_entities = [];

    $local_disabled_entities = $this->subscriberTracker->listTrackedEntities(SubscriberTracker::AUTO_UPDATE_DISABLED);
    if (empty($local_disabled_entities)) {
      return [];
    }

    foreach ($local_disabled_entities as $disabled_entity) {
      $entity_type = $disabled_entity['entity_type'] ?? '';
      $entity_id = $disabled_entity['entity_id'] ?? '';
      $entity_uuid = $disabled_entity['entity_uuid'] ?? '';
      // Non-retrievable entity.
      if ($entity_type === '' || $entity_id === '' || $entity_uuid === '') {
        continue;
      }
      try {
        $entity = $this->entityTypeManager->getStorage($entity_type)->load($entity_id);
      }
      catch (\Exception $e) {
        continue;
      }
      if (!$entity instanceof EntityInterface) {
        continue;
      }
      if ($entity instanceof ConfigEntityInterface) {
        $config_entities[$entity_uuid] = "$entity_type : $entity_uuid";
        continue;
      }
      if ($entity instanceof ContentEntityInterface) {
        $content_entities[$entity_uuid] = "$entity_type : $entity_uuid";
      }
    }
    if (!empty($config_entities)) {
      $this->chLogger->info(
        'All the config entities ({entities}) that were set to AUTO_UPDATE_DISABLED have been skipped for getting updated as disabled for syndication in interest list.',
        ['entities' => implode(', ', array_values($config_entities))]
      );
    }
    return $content_entities;
  }

}
