<?php

declare(strict_types=1);

namespace Drupal\Tests\acquia_dam\Kernel;

use Drupal\acquia_dam\Entity\MediaItemField;
use Drupal\acquia_dam\Entity\MediaSourceField;
use Drupal\acquia_dam\Plugin\Field\FieldType\AssetItem;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\media\Entity\Media;

/**
 * Tests the Asset field item list.
 *
 * @group acquia_dam_kernel
 */
class AssetFieldItemListTest extends AcquiaDamKernelTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $modules = ['token'];

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();
    $this->installConfig(['system']);
  }

  /**
   * Tests generating sample value for the asset field item.
   *
   * @covers \Drupal\acquia_dam\Plugin\Field\FieldType\AssetItem::generateSampleValue
   * @covers \Drupal\acquia_dam\Plugin\media\acquia_dam\Image::generateSampleValue
   */
  public function testAssetFieldItemSampleValueGeneration(): void {
    $media_type = $this->createImageMediaType();
    $field_definition = $this->container->get('entity_field.manager')
      ->getFieldDefinitions('media', $media_type->id())[MediaSourceField::SOURCE_FIELD_NAME] ?? NULL;
    $this->assertInstanceOf(FieldDefinitionInterface::class, $field_definition, 'The media source field definition should exist.');
    $sample_value = AssetItem::generateSampleValue($field_definition);
    $this->assertIsArray($sample_value, 'The sample value should be an array.');
    $this->assertArrayHasKey('asset_id', $sample_value, 'The sample value should have an asset_id key.');
    $this->assertArrayHasKey('version_id', $sample_value, 'The sample value should have a version_id key.');
    $this->assertArrayHasKey('external_id', $sample_value, 'The sample value should have an external_id key.');
  }

  /**
   * Tests that the asset field item values based on the media type's asset
   * download configuration, and updates when the configuration changes.
   *
   * @covers \Drupal\acquia_dam\Plugin\Field\AssetFieldItemList
   * @covers \Drupal\acquia_dam\Plugin\Field\ImageFieldItemList
   */
  public function testAssetFieldItem(): void {
    $media_type = $this->createImageMediaType(['download_assets' => TRUE]);

    $field_definition = $this->container->get('entity_field.manager')
      ->getFieldDefinitions('media', $media_type->id())[MediaSourceField::SOURCE_FIELD_NAME] ?? NULL;
    $this->assertInstanceOf(FieldDefinitionInterface::class, $field_definition, 'The media source field definition should exist.');

    $filename = "wheel-illustration.ai";
    $media = Media::create([
      'name' => $filename,
      'bundle' => $media_type->id(),
      MediaSourceField::SOURCE_FIELD_NAME => AssetItem::generateSampleValue($field_definition),
    ]);
    $media->save();

    // Assert local asset field values.
    $local_field_value = $media->get(MediaItemField::getFieldName('image'))->first()->getValue();
    $this->assertFileExists("public://dam/asset_external_id/$filename", 'The asset file should be downloaded locally.');
    $this->assertNotEmpty($local_field_value, 'The field value should exist.');
    $this->assertSame(['src', 'alt', 'width', 'height'], array_keys($local_field_value), 'The image field should have the correct properties.');
    $this->assertStringEndsWith('/dam/asset_external_id/wheel-illustration.ai', $local_field_value['src'], 'The image field src should point to the downloaded file.');
    $this->assertNotNull($local_field_value['width'], 'The image field width should be set.');
    $this->assertNotNull($local_field_value['height'], 'The image field height should be set.');
    $this->assertSame('wheel-illustration', $local_field_value['alt'], 'The image field alt should be set to the media name.');

    // Disable local asset download and verify DAM field values.
    $media_type->set('source_configuration', ['download_assets' => FALSE])->save();
    $media = $this->container->get('entity_type.manager')->getStorage('media')->load($media->id());

    $dam_field_value = $media->get(MediaItemField::getFieldName('image'))->first()->getValue();
    $this->assertNotEmpty($dam_field_value, 'The field value should exist.');
    $this->assertSame(['src', 'alt', 'width', 'height'], array_keys($dam_field_value), 'The image field should have the correct properties.');
    $this->assertStringStartsWith('https://laser.widen.net/content', $dam_field_value['src'], 'The image field src should point to the DAM asset URL.');
    $this->assertSame('wheel-illustration', $dam_field_value['alt'], 'The image field alt should be set to the media name.');
    $this->assertNotNull($dam_field_value['width'], 'The image field width should be set.');
    $this->assertNotNull($dam_field_value['height'], 'The image field height should be set.');

    // Compare non-src properties for equality.
    foreach (['alt', 'width', 'height'] as $key) {
      $this->assertSame($local_field_value[$key], $dam_field_value[$key]);
    }
  }

}
