<?php

declare(strict_types=1);

namespace Drupal\Tests\config_translation\Unit;

use Drupal\config_translation\ConfigFieldMapper;
use Drupal\Tests\UnitTestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;

/**
 * Tests the functionality provided by the configuration field mapper.
 */
#[CoversClass(ConfigFieldMapper::class)]
#[Group('config_translation')]
class ConfigFieldMapperTest extends UnitTestCase {

  /**
   * The configuration field mapper to test.
   *
   * @var \Drupal\config_translation\ConfigFieldMapper
   */
  protected $configFieldMapper;

  /**
   * The field config instance used for testing.
   *
   * @var \Drupal\field\FieldConfigInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $entity;

  /**
   * The entity type manager used for testing.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $entityTypeManager;

  /**
   * The mocked event dispatcher.
   *
   * @var \Symfony\Contracts\EventDispatcher\EventDispatcherInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $eventDispatcher;

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

    $this->entityTypeManager = $this->createMock('Drupal\Core\Entity\EntityTypeManagerInterface');
    $this->entity = $this->createMock('Drupal\field\FieldConfigInterface');

    $definition = [
      'class' => '\Drupal\config_translation\ConfigFieldMapper',
      'base_route_name' => 'entity.field_config.node_field_edit_form',
      'title' => '@label field',
      'names' => [],
      'entity_type' => 'field_config',
    ];

    $locale_config_manager = $this->getMockBuilder('Drupal\locale\LocaleConfigManager')
      ->disableOriginalConstructor()
      ->getMock();

    $this->eventDispatcher = $this->createMock('Symfony\Contracts\EventDispatcher\EventDispatcherInterface');

    $this->configFieldMapper = new ConfigFieldMapper(
      'node_fields',
      $definition,
      $this->getConfigFactoryStub(),
      $this->createMock('Drupal\Core\Config\TypedConfigManagerInterface'),
      $locale_config_manager,
      $this->createMock('Drupal\config_translation\ConfigMapperManagerInterface'),
      $this->createMock('Drupal\Core\Routing\RouteProviderInterface'),
      $this->getStringTranslationStub(),
      $this->entityTypeManager,
      $this->createMock('Drupal\Core\Language\LanguageManagerInterface'),
      $this->eventDispatcher
    );
  }

  /**
   * Tests ConfigFieldMapper::setEntity().
   */
  public function testSetEntity(): void {
    $entity_type = $this->createMock('Drupal\Core\Config\Entity\ConfigEntityTypeInterface');
    $entity_type
      ->expects($this->any())
      ->method('getConfigPrefix')
      ->willReturn('config_prefix');

    $this->entityTypeManager
      ->expects($this->any())
      ->method('getDefinition')
      ->willReturn($entity_type);

    $field_storage = $this->createMock('Drupal\field\FieldStorageConfigInterface');
    $field_storage
      ->expects($this->any())
      ->method('id')
      ->willReturn('field_storage_id');

    $this->entity
      ->expects($this->any())
      ->method('getFieldStorageDefinition')
      ->willReturn($field_storage);

    $result = $this->configFieldMapper->setEntity($this->entity);
    $this->assertTrue($result);

    // Ensure that the configuration name was added to the mapper.
    $plugin_definition = $this->configFieldMapper->getPluginDefinition();
    $this->assertContains('config_prefix.field_storage_id', $plugin_definition['names']);

    // Make sure setEntity() returns FALSE when called a second time.
    $result = $this->configFieldMapper->setEntity($this->entity);
    $this->assertFalse($result);
  }

}
