<?php

declare(strict_types=1);

namespace Drupal\Tests\acquia_dam\Kernel\Plugin\Linkit\Substitution;

use Drupal\acquia_dam\Plugin\Linkit\Substitution\DamAsset;
use Drupal\media\Entity\Media;
use Drupal\Tests\acquia_dam\Kernel\AcquiaDamKernelTestBase;

/**
 * Tests the DamAsset substitution plugin.
 *
 * @coversDefaultClass \Drupal\acquia_dam\Plugin\Linkit\Substitution\DamAsset
 * @group acquia_dam
 * @group linkit
 */
class DamAssetSubstitutionTest extends AcquiaDamKernelTestBase {

  /**
   * The substitution manager.
   *
   * @var \Drupal\linkit\SubstitutionManagerInterface
   */
  protected $substitutionManager;

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

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'views',
    'file',
    'image',
    'media',
    'media_library',
    'views_remote_data',
    'token',
    'acquia_dam',
    'acquia_dam_test',
    'linkit',
  ];

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();

    $this->installConfig(['linkit']);
    $this->substitutionManager = $this->container->get('plugin.manager.linkit.substitution');
    $this->entityTypeManager = $this->container->get('entity_type.manager');

    // Clear cached definitions to ensure the plugin is discovered.
    $this->substitutionManager->clearCachedDefinitions();
  }

  /**
   * Tests that the plugin is discovered and can be instantiated.
   *
   * @covers ::create
   * @covers ::__construct
   */
  public function testPluginDiscovery() {
    $definitions = $this->substitutionManager->getDefinitions();
    $this->assertArrayHasKey('acquia_dam_asset', $definitions, 'The acquia_dam_asset substitution plugin is discovered.');

    $plugin = $this->substitutionManager->createInstance('acquia_dam_asset');
    $this->assertInstanceOf(DamAsset::class, $plugin, 'The acquia_dam_asset substitution plugin can be instantiated.');
  }

  /**
   * Tests the isApplicable method.
   *
   * @covers ::isApplicable
   */
  public function testIsApplicable() {
    // Test that the plugin is applicable to media entities.
    $media_entity_type = $this->entityTypeManager->getDefinition('media');
    $this->assertTrue(
      DamAsset::isApplicable($media_entity_type),
      'The DamAsset substitution plugin is applicable to media entities.'
    );

    // Test that the plugin is not applicable to other entity types.
    $file_entity_type = $this->entityTypeManager->getDefinition('file');
    $this->assertFalse(
      DamAsset::isApplicable($file_entity_type),
      'The DamAsset substitution plugin is not applicable to file entities.'
    );

    $user_entity_type = $this->entityTypeManager->getDefinition('user');
    $this->assertFalse(
      DamAsset::isApplicable($user_entity_type),
      'The DamAsset substitution plugin is not applicable to user entities.'
    );
  }

  /**
   * Tests the getUrl method with a non-media entity.
   *
   * @covers ::getUrl
   */
  public function testGetUrlWithNonMediaEntity() {
    // Create a user entity (not a media entity).
    $user = $this->createUser();

    // Get the substitution plugin and test getUrl.
    $plugin = $this->substitutionManager->createInstance('acquia_dam_asset');
    $url = $plugin->getUrl($user);

    // The method should fall back to parent::getUrl() which should return NULL
    // for non-media entities.
    $this->assertNull(
      $url,
      'The getUrl method returns NULL for non-media entities.'
    );
  }

  /**
   * Tests the getUrl method with DAM assets.
   *
   * @dataProvider mediaTypeProvider
   * @covers ::getUrl
   */
  public function testGetUrlWithDamAssets($create_method, $media_name, $field_values, $download_assets, $expected_pattern) {
    // Create configuration array with download_assets setting if specified.
    $config = $download_assets ? ['download_assets' => $download_assets] : [];

    // Create a DAM media type using the provided method.
    $media_type = $this->{$create_method}($config);

    // Get the source field name from the media type.
    $source_field_name = $media_type->getSource()->getSourceFieldDefinition($media_type)->getName();

    // Create a media entity with DAM asset.
    $media = Media::create([
      'bundle' => $media_type->id(),
      'name' => $media_name,
      $source_field_name => $field_values,
    ]);
    $media->save();

    // Create the plugin through the manager.
    $plugin = $this->substitutionManager->createInstance('acquia_dam_asset');
    $url = $plugin->getUrl($media);

    // Assert that a URL is returned.
    $this->assertNotNull($url, 'The getUrl method returns a URL for DAM assets.');
    $this->assertStringContainsString($expected_pattern, $url->toString(), 'The generated URL matches the expected pattern.');
  }

  /**
   * Data provider for testGetUrlWithDamAssets.
   *
   * @return array
   *   Array of media type creation methods and expected values.
   */
  public static function mediaTypeProvider() {
    return [
      'image_no_download' => [
        'create_method' => 'createImageMediaType',
        'media_name' => 'Test DAM Asset',
        'field_values' => [
          'asset_id' => 'f2a9c03d-3664-477c-8013-e84504ed5adc',
          'version_id' => '77b3dd66-e590-4259-82db-25e7f4e62772',
          'external_id' => 'm2x3z2j9ou',
        ],
        'download_assets' => FALSE,
        'expected_pattern' => 'https://laser.widen.net/content/m2x3z2j9ou/web/An asset with many versions.png',
      ],
      'image_with_download' => [
        'create_method' => 'createImageMediaType',
        'media_name' => 'Test Downloaded Asset',
        'field_values' => [
          'asset_id' => 'f2a9c03d-3664-477c-8013-e84504ed5adc',
          'version_id' => '77b3dd66-e590-4259-82db-25e7f4e62772',
          'external_id' => 'm2x3z2j9ou',
        ],
        'download_assets' => TRUE,
        'expected_pattern' => '/files/dam/asset_external_id/an-asset-with-many-versions.png',
      ],
      'video_no_download' => [
        'create_method' => 'createVideoMediaType',
        'media_name' => 'Test DAM Video',
        'field_values' => [
          'asset_id' => 'efb03f75-3c42-497b-baa9-5ec79d1f56af',
          'version_id' => '77b3dd66-e590-4259-82db-25e7f4e62778',
          'external_id' => 'mnmc58hipn',
        ],
        'download_assets' => FALSE,
        'expected_pattern' => 'https://laser.widen.net/content/mnmc58hipn/original/SD-Social Promo_.mp4',
      ],
    ];
  }

}
