<?php

declare(strict_types=1);

namespace Drupal\Tests\display_builder\Kernel;

use Drupal\display_builder\Entity\Instance;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;

/**
 * Test some mechanisms $renderable = of the BuilderPanel plugin.
 *
 * @internal
 */
#[CoversClass('\Drupal\display_builder\Plugin\display_builder\Island\BuilderPanel')]
#[Group('display_builder')]
#[RunTestsInSeparateProcesses]
final class BuilderPanelTest extends DisplayBuilderKernelTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'system',
    'user',
    'ui_patterns',
    'ui_patterns_field',
    'display_builder',
    'display_builder_test',
  ];

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();
    $this->installConfig(['system', 'display_builder', 'ui_patterns', 'display_builder_test']);
    $this->installEntitySchema('user');
    $this->installEntitySchema('display_builder_profile');
  }

  /**
   * Test the ::buildSingleBlock() method.
   */
  public function testBuildSingleBlock(): void {
    $instance = Instance::create([
      'id' => 'test_instance',
      'label' => 'Test Instance',
    ]);

    $data = [
      [
        'source_id' => 'block',
        'node_id' => \bin2hex(\random_bytes(8)),
        'source' => [
          'plugin_id' => 'display_builder_test_correct',
        ],
      ],
      [
        'source_id' => 'block',
        'node_id' => \bin2hex(\random_bytes(8)),
        'source' => [
          'plugin_id' => 'display_builder_test_empty',
        ],
      ],
      [
        'source_id' => 'block',
        'node_id' => \bin2hex(\random_bytes(8)),
        'source' => [
          'plugin_id' => 'display_builder_test_multi_root',
        ],
      ],
      [
        'source_id' => 'block',
        'node_id' => \bin2hex(\random_bytes(8)),
        'source' => [
          'plugin_id' => 'display_builder_test_no_attributes',
        ],
      ],
      [
        'source_id' => 'block',
        'node_id' => \bin2hex(\random_bytes(8)),
        'source' => [
          'plugin_id' => 'system_messages_block',
        ],
      ],
      [
        'source_id' => 'entity_field',
        'node_id' => \bin2hex(\random_bytes(8)),
      ],
    ];
    $builder_panel = $this->createIslandPlugin('builder');
    $renderable = $builder_panel->build($instance, $data, [])['#slots']['content'];
    $this->assertNonAltered($renderable[0]);
    $this->assertPlaceholder($renderable[1]);
    $this->assertWrapper($renderable[2]);
    $this->assertWrapper($renderable[3]);
    $this->assertPlaceholder($renderable[4]);
    self::assertStringStartsWith('Field: ', $renderable[5]['#slots']['content']);
  }

  /**
   * Assert the block renderable was not altered.
   *
   * @param array $renderable
   *   The block renderable, as generated by the BuilderPanel island.
   */
  private function assertNonAltered(array $renderable): void {
    $block = $this->container->get('plugin.manager.block')->createInstance('display_builder_test_correct');
    $expectations = $block->build();
    // We don't check #attributes because they got the HTMX additions.
    unset($renderable['#attributes'], $expectations['#attributes']);
    self::assertSame($expectations, $renderable);
  }

  /**
   * Assert the block renderable was replaced by a placeholder.
   *
   * @param array $renderable
   *   The block renderable, as generated by the BuilderPanel island.
   */
  private function assertPlaceholder(array $renderable): void {
    self::assertSame('component', $renderable['#type']);
    self::assertSame('display_builder:placeholder', $renderable['#component']);
  }

  /**
   * Assert the block renderable was put in a wrapper.
   *
   * @param array $renderable
   *   The block renderable, as generated by the BuilderPanel island.
   */
  private function assertWrapper(array $renderable): void {
    self::assertSame('html_tag', $renderable['#type']);
    self::assertArrayHasKey('content', $renderable);
  }

}
