<?php

namespace Drupal\acquia_contenthub_subscriber;

use Acquia\ContentHubClient\ContentHubClient;
use Drupal\acquia_contenthub\Settings\ContentHubConfigurationInterface;
use Drupal\acquia_contenthub_subscriber\Libs\UserDeletionHandlerInterface;
use Drupal\Component\Uuid\Uuid;
use Drupal\Core\Entity\EntityInterface;

/**
 * Base class for entity deletion handling.
 *
 * Provides common functionality for deleting entities across different
 * contexts (webhooks and service queue).
 *
 * @package Drupal\acquia_contenthub_subscriber
 */
class EntityDeletionHandlerBase {

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

  /**
   * CH configurations.
   *
   * @var \Drupal\acquia_contenthub\Settings\ContentHubConfigurationInterface
   */
  protected ContentHubConfigurationInterface $achConfigurations;

  /**
   * User deletion handler service.
   *
   * @var \Drupal\acquia_contenthub_subscriber\Libs\UserDeletionHandlerInterface
   */
  protected UserDeletionHandlerInterface $userDeletionHandler;

  /**
   * Constructs an EntityDeletionHandlerBase object.
   *
   * @param \Drupal\acquia_contenthub_subscriber\SubscriberTracker $tracker
   *   The subscription tracker.
   * @param \Drupal\acquia_contenthub\Settings\ContentHubConfigurationInterface $ch_configuration
   *   CH Configurations.
   * @param \Drupal\acquia_contenthub_subscriber\Libs\UserDeletionHandlerInterface $handler
   *   The user deletion handler service.
   */
  public function __construct(SubscriberTracker $tracker, ContentHubConfigurationInterface $ch_configuration, UserDeletionHandlerInterface $handler) {
    $this->tracker = $tracker;
    $this->achConfigurations = $ch_configuration;
    $this->userDeletionHandler = $handler;
  }

  /**
   * Processes multiple entity deletions.
   *
   * @param array $entity_uuids
   *   Array of entity UUIDs to delete.
   * @param array $entity_uuids_to_cleanup
   *   Reference to array for collecting UUIDs of entities not found locally.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function processMultipleEntityDeletions(array $entity_uuids, array &$entity_uuids_to_cleanup): void {
    if (empty($entity_uuids)) {
      return;
    }

    $uuid_hash_map = array_fill_keys($entity_uuids, NULL);
    $entities = $this->tracker->getEntitiesByRemoteIdAndHash($uuid_hash_map);
    $found_uuids = array_keys($entities);
    $missing_uuids = array_diff($entity_uuids, $found_uuids);
    $entity_uuids_to_cleanup = array_merge($entity_uuids_to_cleanup, $missing_uuids);

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

    $statuses = $this->tracker->getStatusesByUuids($found_uuids);
    $auto_update_disabled_uuids = [];

    foreach ($entities as $uuid => $entity) {
      $status = $statuses[$uuid] ?? NULL;

      // If entity updating is disabled, delete tracking but not the entity.
      if ($status === SubscriberTracker::AUTO_UPDATE_DISABLED) {
        $auto_update_disabled_uuids[] = $uuid;
      }
      else {
        $this->deleteEntity($entity);
      }
    }

    if (!empty($auto_update_disabled_uuids)) {
      $this->tracker->deleteMultipleByUuids($auto_update_disabled_uuids);
    }
  }

  /**
   * Deletes an entity based on its type.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity to delete.
   */
  protected function deleteEntity(EntityInterface $entity): void {
    $entity_type_id = $entity->getEntityTypeId();

    if ($entity_type_id === 'user') {
      /** @var \Drupal\user\UserInterface $entity */
      $this->userDeletionHandler->blockUser($entity);
      return;
    }

    if ($entity_type_id === 'user_role') {
      /** @var \Drupal\user\RoleInterface $entity */
      $this->userDeletionHandler->deleteUserRole($entity);
      return;
    }

    // Delete the entity for all other types.
    $entity->delete();
  }

  /**
   * Cleans up tracking data and Content Hub interests for missing entities.
   *
   * @param array $entity_uuids
   *   Array of entity UUIDs to clean up.
   * @param \Acquia\ContentHubClient\ContentHubClient $client
   *   The Content Hub Client.
   */
  protected function cleanupMissingEntities(array $entity_uuids, ContentHubClient $client): void {
    if (empty($entity_uuids)) {
      return;
    }

    $settings = $client->getSettings();
    $send_update = $this->achConfigurations->getContentHubConfig()->shouldSendContentHubUpdates();

    // Clean up the tracker. The entity was deleted before import.
    $this->tracker->deleteMultipleByUuids($entity_uuids);

    $webhook_uuid = $settings->getWebhook('uuid');
    if ($send_update && Uuid::isValid($webhook_uuid)) {
      $client->deleteMultipleInterest($webhook_uuid, $entity_uuids, 'subscriber');
    }
  }

  /**
   * Determines if given entity type is supported.
   *
   * @param string|null $type
   *   The CDF type.
   *
   * @return bool
   *   TRUE if is supported type; FALSE otherwise.
   */
  protected function isSupportedType(?string $type): bool {
    if (!$type) {
      return FALSE;
    }

    $supported_types = [
      'drupal8_content_entity',
      'drupal8_config_entity',
    ];

    return in_array($type, $supported_types, TRUE);
  }

}
