<?php

declare(strict_types=1);

namespace Drupal\acquia_dam;

use Drupal\acquia_dam\Plugin\media\Source\Asset;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldDefinitionListenerInterface;
use Psr\Log\LoggerInterface;

/**
 * Service for registering Acquia DAM bundle fields in the field map.
 */
class BundleFieldMapService {

  /**
   * Constructs a BundleFieldMapService.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entity type manager.
   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager
   *   The entity field manager.
   * @param \Drupal\Core\Field\FieldDefinitionListenerInterface $fieldDefinitionListener
   *   The field definition listener.
   * @param \Psr\Log\LoggerInterface $logger
   *   The logger.
   */
  public function __construct(
    protected EntityTypeManagerInterface $entityTypeManager,
    protected EntityFieldManagerInterface $entityFieldManager,
    protected FieldDefinitionListenerInterface $fieldDefinitionListener,
    protected LoggerInterface $logger,
  ) {}

  /**
   * Registers all Acquia DAM bundle fields in the field map.
   *
   * @return void
   */
  public function registerBundleFields(): void {
    $media_entity_type = $this->entityTypeManager->getDefinition('media');
    $dam_bundles = $this->getDamMediaBundles();

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

    foreach ($dam_bundles as $bundle) {
      $bundle_fields = acquia_dam_entity_bundle_field_info(
        $media_entity_type,
        $bundle,
        []
      );

      foreach ($bundle_fields as $field_definition) {
        $this->fieldDefinitionListener->onFieldDefinitionCreate($field_definition);
      }
    }

    // Clear field caches to ensure the changes take effect.
    $this->entityFieldManager->clearCachedFieldDefinitions();
  }

  /**
   * Unregisters Acquia DAM bundle fields from the field map.
   *
   * @param string $bundle
   *   The bundle ID to unregister fields for.
   *
   * @return void
   */
  public function unregisterBundleFields(string $bundle): void {
    $media_entity_type = $this->entityTypeManager->getDefinition('media');

    // Get the bundle fields that were registered.
    $bundle_fields = acquia_dam_entity_bundle_field_info(
      $media_entity_type,
      $bundle,
      []
    );

    // Notify the field definition listener about each field deletion.
    foreach ($bundle_fields as $field_definition) {
      $this->fieldDefinitionListener->onFieldDefinitionDelete($field_definition);
    }

    // Clear field caches to ensure the changes take effect.
    $this->entityFieldManager->clearCachedFieldDefinitions();
  }

  /**
   * Gets all media bundles using Acquia DAM source.
   *
   * @return array
   *   Array of bundle IDs.
   */
  protected function getDamMediaBundles(): array {
    $dam_bundles = [];

    try {
      $media_types = $this->entityTypeManager
        ->getStorage('media_type')
        ->loadMultiple();

      foreach ($media_types as $bundle_id => $media_type) {
        $source = $media_type->getSource();
        if ($source instanceof Asset) {
          $dam_bundles[] = $bundle_id;
        }
      }
    }
    catch (\Exception $e) {
      $this->logger->error('Error loading media types: @error', [
        '@error' => $e->getMessage(),
      ]);
    }

    return $dam_bundles;
  }

}
