<?php

namespace Drupal\acquia_contenthub_publisher\EventSubscriber\Config;

use Drupal\acquia_contenthub_publisher\Libs\ExcludeSettingsInterface;
use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Class BundleConfigSubscriber.
 *
 * Removes excluded fields from settings when bundle config is deleted.
 */
class BundleConfigSubscriber implements EventSubscriberInterface {

  /**
   * The exclude settings.
   *
   * @var \Drupal\acquia_contenthub_publisher\Libs\ExcludeSettingsInterface
   */
  protected ExcludeSettingsInterface $excludeSettings;

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

  /**
   * BundleConfigSubscriber constructor.
   *
   * @param \Drupal\acquia_contenthub_publisher\Libs\ExcludeSettingsInterface $excludeSettings
   *   The exclude settings.
   * @param \Psr\Log\LoggerInterface $logger
   *   The logger.
   */
  public function __construct(ExcludeSettingsInterface $excludeSettings, LoggerInterface $logger) {
    $this->excludeSettings = $excludeSettings;
    $this->logger = $logger;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    $events[ConfigEvents::DELETE][] = 'onConfigDelete';
    return $events;
  }

  /**
   * Removes excluded fields from settings when bundle config is deleted.
   *
   * @param \Drupal\Core\Config\ConfigCrudEvent $event
   *   The config crud event.
   */
  public function onConfigDelete(ConfigCrudEvent $event): void {
    $config_name = $event->getConfig()->getName();
    if (!$config_name || !$this->isBundleConfig($config_name)) {
      return;
    }
    $bundle_info = $this->getEntityTypeAndBundleFromConfig($config_name);
    $this->removeExcludedFieldsByBundle($bundle_info);
  }

  /**
   * Removes excluded fields by bundle.
   *
   * @param array $bundle_info
   *   The bundle info.
   */
  protected function removeExcludedFieldsByBundle(array $bundle_info): void {
    $removable_fields = $this->excludeSettings->getExcludedFields($bundle_info['entity_type'], $bundle_info['bundle']);
    if ($this->excludeSettings->removeExcludedFields($bundle_info['entity_type'], $bundle_info['bundle'], $removable_fields)) {
      $this->logger->info('Excluded fields removed from settings for Type: {entity_type} and Bundle: {bundle}.', [
        'entity_type' => $bundle_info['entity_type'],
        'bundle' => $bundle_info['bundle'],
      ]);
    }
  }

  /**
   * Get entity type and bundle from config name.
   *
   * @param string $config_name
   *   The config name.
   *
   * @return array
   *   The entity type and bundle.
   */
  protected function getEntityTypeAndBundleFromConfig(string $config_name): array {
    [$entity_type_id, , $bundle_id] = explode('.', $config_name);
    return [
      'entity_type' => $entity_type_id,
      'bundle' => $bundle_id,
    ];
  }

  /**
   * Checks if the config name is a bundle definition config.
   *
   * @param string $config_name
   *   The config name.
   *
   * @return bool
   *   TRUE if the config name is a bundle definition config, FALSE otherwise.
   */
  protected function isBundleConfig(string $config_name): bool {
    $parts = explode('.', $config_name);
    // Bundle config follows pattern as '{entity_type_id}.type.{bundle_id}'.
    return count($parts) === 3 && preg_match('/^.+\.type\..+$/', $config_name);
  }

}
