<?php

namespace Drupal\Tests\search_api\Kernel\Index;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\KernelTests\KernelTestBase;
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;

/**
 * Tests whether importing of index configuration works correctly.
 *
 * @group search_api
 */
#[RunTestsInSeparateProcesses]
class IndexImportTest extends KernelTestBase {

  /**
   * The entity type manager.
   */
  protected EntityTypeManagerInterface $entityTypeManager;

  /**
   * Modules to enable for this test.
   *
   * @var string[]
   */
  protected static $modules = [
    'field',
    'search_api',
    'search_api_db',
    'search_api_test_db',
    'search_api_test',
    'user',
    'system',
    'entity_test',
    'text',
  ];

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

    $this->installSchema('search_api', ['search_api_item']);
    $this->installSchema('user', ['users_data']);
    $this->installEntitySchema('entity_test_mulrev_changed');
    $this->installEntitySchema('search_api_task');
    $this->installConfig('search_api');
    $this->installConfig('system');
    $this->config('system.site')->set('UUID', $this->container->get('uuid')->generate());

    $this->installConfig(['search_api_test_db']);

    $this->entityTypeManager = $this->container->get('entity_type.manager');
  }

  /**
   * Tests processors are set after import.
   */
  public function testIndexImport() {
    // Check initial conditions.
    /** @var \Drupal\search_api\IndexInterface $index */
    $index = $this->entityTypeManager->getStorage('search_api_index')->load('database_search_index');
    $this->assertFalse($index->isValidProcessor('stopwords'), 'Processor is not in index');

    // Prepare the import by creating a copy of the active config in sync.
    /** @var \Drupal\Core\Config\StorageInterface $sync */
    $sync = $this->container->get('config.storage.sync');
    /** @var \Drupal\Core\Config\StorageInterface $active */
    $active = $this->container->get('config.storage');
    $this->copyConfig($active, $sync);

    // Make changes to the configuration in "sync" so there actually is
    // something to import.
    $expected_stopwords = ['a', 'an', 'and', 'are', 'as'];
    $import_config = $sync->read('search_api.index.database_search_index');
    $import_config['processor_settings']['stopwords'] = [
      'weights' => [
        'preprocess_query' => -10,
        'postprocess_query' => -10,
      ],
      'fields' => [
        'name',
      ],
      'stopwords' => $expected_stopwords,
    ];
    $sync->write('search_api.index.database_search_index', $import_config);

    // Import the test configuration.
    $config_importer = $this->configImporter();
    $this->assertTrue($config_importer->hasUnprocessedConfigurationChanges(), 'Import prepared');
    $config_importer->import();

    // Ensure the static cache is clear and check that our change was correctly
    // imported.
    $this->entityTypeManager->getStorage('search_api_index')->resetCache(['database_search_index']);
    /** @var \Drupal\search_api\IndexInterface $imported_index */
    $imported_index = $this->entityTypeManager->getStorage('search_api_index')->load('database_search_index');
    $this->assertTrue($imported_index->isValidProcessor('stopwords'), 'Processor is in index after import');

    // Check that the processor does not have the default configuration.
    $processor_config = $imported_index->getProcessor('stopwords')->getConfiguration();
    $this->assertArrayHasKey('stopwords', $processor_config, 'Stopwords are configured');
    $actual_stopwords = $processor_config['stopwords'];
    $this->assertEquals($expected_stopwords, $actual_stopwords, 'Processor config was correctly set during import');
  }

}
