<?php

declare(strict_types=1);

namespace Drupal\Tests\acquia_dam\Kernel;

use Drupal\acquia_dam\Entity\MediaSourceField;
use Drupal\media\Entity\Media;
use Drupal\Tests\ckeditor5\Kernel\CKEditor5ValidationTestTrait;

/**
 * Tests the Asset dynamic field type.
 *
 * @group acquia_dam_kernel
 * @coversDefaultClass \Drupal\acquia_dam\Plugin\Field\FieldType\AssetFieldType
 * @covers \Drupal\acquia_dam\Plugin\Field\FieldType\ImageFieldType
 */
class AssetFieldTypeTest extends AcquiaDamKernelTestBase {

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();
    if (version_compare(\Drupal::VERSION, '11.2', '>')) {
      $this->markTestSkipped('This test is skipped for Drupal Core 11.2 and above, as AssetFieldTypeWithCanvasTest provides coverage for newer versions.
      @see \Drupal\Tests\acquia_dam\Kernel\AssetFieldTypeWithCanvasTest');
    }
    $this->installConfig(['media', 'media_library', 'acquia_dam']);
  }

  /**
   * Tests that dynamic asset fields are correctly populated for each media type.
   *
   * @param array $values
   *   The values to use when creating the media entity, including bundle and source field data.
   * @param array $expected_field_data
   *   The expected field data to assert on the created media entity.
   * @param array $expected_field_properties
   *   The expected property definitions for each dynamic field to assert.
   *
   * @dataProvider assetFieldDataProvider
   */
  public function testAssetDynamicField(array $values, array $expected_field_data, array $expected_field_properties): void {
    $media = Media::create($values);
    self::assertSame([], self::violationsToArray($media->validate()));
    $media->save();
    foreach ($expected_field_data as $field => $value) {
      $this->assertTrue($media->hasField($field));
      $field_item = $media->get($field)->first();
      self::assertSame($value, $field_item->getValue());
    }
    foreach ($expected_field_properties as $field => $expected_property_definitions) {
      $field_item = $media->get($field)->first();
      $property_definitions = $field_item::propertyDefinitions($field_item->getFieldDefinition());
      self::assertEqualsCanonicalizing(
        array_keys($expected_property_definitions),
        array_keys($property_definitions),
        sprintf("'Property keys for field '%s' match expected.'", $field)
      );
      foreach ($expected_property_definitions as $property => $expected_methods) {
        foreach ($expected_methods as $method => $expected_property_value) {
          self::assertTrue(
            method_exists($property_definitions[$property], $method),
            sprintf("Method '%s' should exist on property definition '%s'.", $method, $property)
          );
          self::assertSame(
            $expected_property_value,
            $property_definitions[$property]->{$method}(),
            sprintf("Property definition method '%s' on '%s' should return expected value.", $method, $property)
          );
        }
      }
    }
  }

  /**
   * Provides test data for different Acquia DAM asset types and their expected fields.
   *
   * @return \Generator
   *   Yields arrays with 'values' for media creation and 'expected_field_data' for assertions.
   */
  public static function assetFieldDataProvider(): \Generator {
    $common_property = [
      'src' => [
        'getDataType' => 'uri',
        'isReadOnly' => TRUE,
        'isRequired' => TRUE,
        'isComputed' => FALSE,
        'getConstraints' => [
          'PrimitiveType' => [],
          'NotNull' => [],
        ],
      ],
    ];
    yield 'acquia_dam:image' => [
      'values' => [
        'name' => 'Test Image Asset',
        'bundle' => 'acquia_dam_image_asset',
        MediaSourceField::SOURCE_FIELD_NAME => [
          'asset_id' => '56ff14de-02cd-41b5-9a73-c917eab19abf',
          'external_id' => 'kcnabdscl5',
        ],
      ],
      'expected_field_data' => [
        'acquia_dam_image_item' => [
          'src' => 'https://laser.widen.net/content/kcnabdscl5/web/Wheel%20Illustration.ai',
          'alt' => 'Test Image Asset',
          'width' => 157,
          'height' => 120,
        ]
      ],
      'expected_field_properties' => [
        'acquia_dam_image_item' => [
          'alt' => [
            'getDataType' => 'string',
            'isReadOnly' => TRUE,
            'isRequired' => FALSE,
            'isComputed' => FALSE,
            'getConstraints' => [
              'PrimitiveType' => [],
            ],
          ],
          'width' => [
            'getDataType' => 'integer',
            'isReadOnly' => TRUE,
            'isRequired' => FALSE,
            'isComputed' => FALSE,
            'getConstraints' => [
              'PrimitiveType' => [],
            ],
          ],
          'height' => [
            'getDataType' => 'integer',
            'isReadOnly' => TRUE,
            'isRequired' => FALSE,
            'isComputed' => FALSE,
            'getConstraints' => [
              'PrimitiveType' => [],
            ],
          ],
          ...$common_property,
        ],
      ],
    ];
    yield 'acquia_dam:video' => [
      'values' => [
        'name' => 'Test Video Asset',
        'bundle' => 'acquia_dam_video_asset',
        MediaSourceField::SOURCE_FIELD_NAME => [
          'asset_id' => 'efb03f75-3c42-497b-baa9-5ec79d1f56af',
          'external_id' => 'mnmc58hipn',
        ],
      ],
      'expected_field_data' => [
        'acquia_dam_video_item' => [
          'src' => 'https://laser.widen.net/content/mnmc58hipn/original/SD-Social%20Promo.mp4',
        ]
      ],
      'expected_field_properties' => [
        'acquia_dam_video_item' => [
          ...$common_property,
        ],
      ],
    ];

    yield 'acquia_dam:pdf' => [
      'values' => [
        'name' => 'Test Pdf Asset',
        'bundle' => 'acquia_dam_pdf_asset',
        MediaSourceField::SOURCE_FIELD_NAME => [
          'asset_id' => '4f656c07-6a08-47b3-9403-16082d2fcda2',
          'external_id' => '8q3z9gm2ec',
        ],
      ],
      'expected_field_data' => [
        'acquia_dam_pdf_item' => [
          'src' => 'https://laser.widen.net/content/8q3z9gm2ec/original/test-course-catalog-v2.pdf',
        ]
      ],
      'expected_field_properties' => [
        'acquia_dam_pdf_item' => [
          ...$common_property,
        ],
      ],
    ];

    yield 'acquia_dam:documents' => [
      'values' => [
        'name' => 'Test Documents Asset',
        'bundle' => 'acquia_dam_documents_asset',
        MediaSourceField::SOURCE_FIELD_NAME => [
          'asset_id' => 'abab96ac-c2ed-40b1-aaf7-56a52f898230',
          'external_id' => 'rfnwimkigc',
        ],
      ],
      'expected_field_data' => [
        'acquia_dam_documents_item' => [
          'src' => 'https://laser.widen.net/content/rfnwimkigc/original/Best%20Practice%20-%20Content%20Architecture%20-%20v2.1.pptx',
        ]
      ],
      'expected_field_properties' => [
        'acquia_dam_documents_item' => [
          ...$common_property,
        ],
      ],
    ];

    yield 'acquia_dam:generic' => [
      'values' => [
        'name' => 'Test Generic Asset',
        'bundle' => 'acquia_dam_generic_asset',
        MediaSourceField::SOURCE_FIELD_NAME => [
          'asset_id' => 'eec6d92b-6452-4ab6-894a-b4d0826e65ba',
          'external_id' => 'yjezd5iwh5',
        ],
      ],
      'expected_field_data' => [
        'acquia_dam_generic_item' => [
          'src' => 'https://laser.widen.net/content/yjezd5iwh5/original/eudaimonia_spin.zip',
        ]
      ],
      'expected_field_properties' => [
        'acquia_dam_generic_item' => [
          ...$common_property,
        ],
      ],
    ];

  }

}
