<?php

namespace Drupal\Tests\acquiadam_asset_import\Kernel\Services;

use Drupal\KernelTests\KernelTestBase;
use Drupal\acquiadam_asset_import\Services\AssetImportUtilityService;
use Drupal\Tests\acquia_dam\Kernel\AcquiaDamKernelTestBase;

/**
 * Kernel tests for AssetImportUtilityService.
 *
 * @group acquiadam_asset_import
 * @coversDefaultClass \Drupal\acquiadam_asset_import\Services\AssetImportUtilityService
 */
final class AssetImportUtilityServiceTest extends AcquiaDamKernelTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $modules = ['acquiadam_asset_import'];

  /**
   * The service under test.
   *
   * @var \Drupal\acquiadam_asset_import\Services\AssetImportUtilityService
   */
  protected $service;

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();
    $this->service = $this->container->get('acquiadam_asset_import.utility');
  }

  /**
   * Data provider for category key encoding/decoding tests.
   *
   * @return array
   *   Test cases with category keys to test.
   */
  public static function categoryKeyProvider(): array {
    return [
      'simple key' => ['simple'],
      'key with dots' => ['with.dots'],
      'key with dashes' => ['with-dashes'],
      'key with underscores' => ['with_underscores'],
      'key with spaces' => ['with spaces'],
      'key with special characters' => ['special!@#$%^&*()'],
      'complex nested key' => ['category.subcategory.item'],
    ];
  }

  /**
   * Tests encoding and decoding round trip with various keys.
   *
   * @covers ::decodeCategoryKey
   *
   * @dataProvider categoryKeyProvider
   */
  public function testEncodeDecodeRoundTrip(string $key): void {
    $encoded = base64_encode($key);
    $decoded = $this->service->decodeCategoryKey($encoded);

    $this->assertEquals($key, $decoded, "Failed round trip for key: $key");
    $this->assertNotEquals($key, $encoded, "Key should be encoded: $key");
    $this->assertEquals($key, base64_decode($encoded, TRUE), "Encoded key should be valid base64");
  }

  /**
   * Tests backward compatibility with unencoded keys.
   *
   * @covers ::decodeCategoryKey
   */
  public function testDecodeCategoryKeyBackwardCompatibility(): void {
    $plainKey = 'simple_category';
    $decoded = $this->service->decodeCategoryKey($plainKey);

    $this->assertEquals($plainKey, $decoded);
  }

  /**
   * Data provider for config key encoding/decoding tests.
   *
   * @return array
   *   Test cases with configuration arrays.
   */
  public static function configKeysProvider(): array {
    return [
      'simple config' => [
        [
          'category.one' => 'value1',
          'category.two' => 'value2',
          'simple' => 'value3',
        ],
      ],
      'nested config values' => [
        [
          'category.with.dots' => ['field' => 'value1'],
          'another.category' => ['field' => 'value2'],
          'simple_key' => ['field' => 'value3'],
        ],
      ],
      'complex nested structure' => [
        [
          'parent.child.grandchild' => [
            'nested' => ['deeply' => 'value'],
            'array' => [1, 2, 3],
          ],
          'another.key' => 'simple_value',
        ],
      ],
      'empty array' => [[]],
    ];
  }

  /**
   * Tests encoding and decoding config keys round trip.
   *
   * @covers ::encodeConfigKeys
   * @covers ::decodeConfigKeys
   *
   * @dataProvider configKeysProvider
   */
  public function testEncodeDecodeConfigKeysRoundTrip(array $original): void {
    $encoded = $this->service->encodeConfigKeys($original);
    $decoded = $this->service->decodeConfigKeys($encoded);

    $this->assertEquals($original, $decoded);

    // Verify that original keys are not present in encoded array.
    if (!empty($original)) {
      foreach (array_keys($original) as $key) {
        $this->assertArrayNotHasKey($key, $encoded, "Original key '$key' should not be present in encoded array");
      }
    }
  }

  /**
   * Tests encoding configuration keys structure.
   *
   * @covers ::encodeConfigKeys
   */
  public function testEncodeConfigKeysStructure(): void {
    $config = [
      'category.one' => 'value1',
      'category.two' => 'value2',
      'simple' => 'value3',
    ];

    $encoded = $this->service->encodeConfigKeys($config);

    $this->assertCount(3, $encoded);

    // Verify all values are preserved.
    $this->assertContains('value1', $encoded);
    $this->assertContains('value2', $encoded);
    $this->assertContains('value3', $encoded);

    // Verify original keys are encoded.
    foreach (array_keys($config) as $key) {
      $this->assertArrayNotHasKey($key, $encoded);
    }
  }

  /**
   * Tests decoding configuration keys structure.
   *
   * @covers ::decodeConfigKeys
   */
  public function testDecodeConfigKeysStructure(): void {
    $config = [
      base64_encode('category.one') => 'value1',
      base64_encode('category.two') => 'value2',
    ];

    $decoded = $this->service->decodeConfigKeys($config);

    $this->assertArrayHasKey('category.one', $decoded);
    $this->assertArrayHasKey('category.two', $decoded);
    $this->assertEquals('value1', $decoded['category.one']);
    $this->assertEquals('value2', $decoded['category.two']);
  }

  /**
   * Tests service integration with Drupal container.
   */
  public function testServiceIntegration(): void {
    $service = $this->container->get('acquiadam_asset_import.utility');
    $this->assertInstanceOf(AssetImportUtilityService::class, $service);
  }

}
