<?php

declare(strict_types=1);

namespace Drupal\Tests\simple_interactive_maps\Kernel;

use Drupal\KernelTests\KernelTestBase;
use Drupal\simple_interactive_maps\Entity\InteractiveMap;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;

/**
 * Regression guard for the MapBuilder event dispatcher fix.
 *
 * MapBuilder used to type-hint its injected event dispatcher as
 * Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher, a class
 * that does not exist. That was a hard fatal error the very first time any
 * map was rendered. This test exercises the real, container-built service
 * (as simple_interactive_maps.map_builder is wired in
 * simple_interactive_maps.services.yml) and confirms MapBuildEvent actually
 * reaches simple_interactive_maps.event_subscriber, which is the only way
 * this assertion could pass.
 */
#[Group('simple_interactive_maps')]
#[CoversClass(\Drupal\simple_interactive_maps\MapBuilder::class)]
#[RunTestsInSeparateProcesses]
final class MapBuilderTest extends KernelTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'system',
    'filter',
    'field_group',
    'simple_interactive_maps',
  ];

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

  /**
   * Builds a map whose regions cover every key the plugin provides.
   *
   * Mirrors the way InteractiveMapForm::save() seeds a newly created map.
   */
  private function createFullyConfiguredMap(): InteractiveMap {
    /** @var \Drupal\simple_interactive_maps\MapDefinitionPluginManager $pluginManager */
    $pluginManager = $this->container->get('plugin.manager.map_definition');
    $plugin = $pluginManager->createInstance('us_states_territories');

    $regions = [];
    foreach ($plugin->mapData() as $key => $value) {
      $regions[$key] = [
        'id' => $key,
        'label' => $value['label'],
        'hidden' => 0,
        'group' => '',
        'fill_color' => '#4ba0a6',
        'hover_color' => '#076369',
        'stroke_color' => '#e6e6e6',
        'text_color' => '#000000',
        'tooltip' => ['value' => '', 'format' => 'plain_text'],
        'action' => ['plugin_id' => 'none', 'plugin_configuration' => []],
      ];
    }

    $map = InteractiveMap::create([
      'id' => 'test_map',
      'label' => 'Test Map',
      'base_map' => 'us_states_territories',
      'regions' => $regions,
    ]);
    $map->save();

    return $map;
  }

  /**
   * Tests that the render helper contains the render array and settings.
   */
  public function testRenderHelperContainsRenderArrayAndSettings(): void {
    $map = $this->createFullyConfiguredMap();

    /** @var \Drupal\simple_interactive_maps\MapBuilder $mapBuilder */
    $mapBuilder = $this->container->get('simple_interactive_maps.map_builder');
    $renderHelper = $mapBuilder->getRenderHelper($map);

    $renderArray = $renderHelper->getRenderArray();
    $this->assertSame('svg', $renderArray['#tag']);
    $this->assertNotEmpty($renderHelper->getSettings());
  }

  /**
   * Regression guard confirming MapBuildEvent reaches the core subscriber.
   *
   * The simple_interactive_maps.event_subscriber service only mutates the
   * render array for the 'thumbnail' context, so this only passes if
   * MapBuildEvent was actually dispatched and received.
   */
  public function testMapBuildEventReachesTheCoreSubscriber(): void {
    $map = $this->createFullyConfiguredMap();

    /** @var \Drupal\simple_interactive_maps\MapBuilder $mapBuilder */
    $mapBuilder = $this->container->get('simple_interactive_maps.map_builder');
    $renderHelper = $mapBuilder->getRenderHelper($map, 'thumbnail');

    $renderArray = $renderHelper->getRenderArray();
    $this->assertSame(300, $renderArray['#attributes']['height']);
  }

  /**
   * Tests that the render helper is cached per context.
   */
  public function testRenderHelperIsCachedPerContext(): void {
    $map = $this->createFullyConfiguredMap();

    /** @var \Drupal\simple_interactive_maps\MapBuilder $mapBuilder */
    $mapBuilder = $this->container->get('simple_interactive_maps.map_builder');

    $default = $mapBuilder->getRenderHelper($map);
    $thumbnail = $mapBuilder->getRenderHelper($map, 'thumbnail');

    // Different contexts must not share a cache entry: only the thumbnail
    // build should have the height override from the subscriber.
    $this->assertArrayNotHasKey('height', $default->getRenderArray()['#attributes']);
    $this->assertSame(300, $thumbnail->getRenderArray()['#attributes']['height']);

    // Calling again with the same context should hit the cache and return
    // an equivalent result.
    $secondDefault = $mapBuilder->getRenderHelper($map);
    $this->assertSame($default->getSettings(), $secondDefault->getSettings());
  }

}
