<?php

namespace Drupal\Tests\eb\Unit;

use Drupal\eb\PluginManager\EbExtensionPluginManager;
use Drupal\eb\Service\ChangeDetection\ChangeDetector;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use PHPUnit\Framework\TestCase;

/**
 * Tests for ChangeDetector service.
 *
 * @coversDefaultClass \Drupal\eb\Service\ChangeDetection\ChangeDetector
 * @group eb
 *
 * Note: Most ChangeDetector functionality requires integration with
 * Drupal entities and is better tested with kernel tests.
 * These unit tests focus on isolated helper methods.
 */
class ChangeDetectorTest extends TestCase {

  /**
   * The change detector service.
   */
  protected ChangeDetector $changeDetector;

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

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

    // Mock entity type manager.
    $this->entityTypeManager = $this->createMock(EntityTypeManagerInterface::class);

    $extensionManager = $this->createMock(EbExtensionPluginManager::class);
    $extensionManager->method('getExtensions')->willReturn([]);
    $this->changeDetector = new ChangeDetector($this->entityTypeManager, $extensionManager);
  }

  /**
   * Tests valuesAreDifferent with scalars.
   *
   * @covers ::valuesAreDifferent
   */
  public function testValuesAreDifferentScalars(): void {
    $reflection = new \ReflectionClass($this->changeDetector);
    $method = $reflection->getMethod('valuesAreDifferent');
    $method->setAccessible(TRUE);

    $this->assertFalse($method->invoke($this->changeDetector, 'test', 'test'));
    $this->assertTrue($method->invoke($this->changeDetector, 'test', 'different'));
    $this->assertFalse($method->invoke($this->changeDetector, 123, 123));
    $this->assertTrue($method->invoke($this->changeDetector, 123, 456));
  }

  /**
   * Tests valuesAreDifferent with arrays.
   *
   * @covers ::valuesAreDifferent
   */
  public function testValuesAreDifferentArrays(): void {
    $reflection = new \ReflectionClass($this->changeDetector);
    $method = $reflection->getMethod('valuesAreDifferent');
    $method->setAccessible(TRUE);

    $array1 = ['a' => 1, 'b' => 2];
    $array2 = ['a' => 1, 'b' => 2];
    $array3 = ['a' => 1, 'b' => 3];

    $this->assertFalse($method->invoke($this->changeDetector, $array1, $array2));
    $this->assertTrue($method->invoke($this->changeDetector, $array1, $array3));
  }

  /**
   * Tests valuesAreDifferent with null.
   *
   * @covers ::valuesAreDifferent
   */
  public function testValuesAreDifferentNull(): void {
    $reflection = new \ReflectionClass($this->changeDetector);
    $method = $reflection->getMethod('valuesAreDifferent');
    $method->setAccessible(TRUE);

    $this->assertFalse($method->invoke($this->changeDetector, NULL, NULL));
    $this->assertTrue($method->invoke($this->changeDetector, NULL, 'test'));
    $this->assertTrue($method->invoke($this->changeDetector, 'test', NULL));
  }

}
