<?php

declare(strict_types=1);

namespace Drupal\Tests\flowdrop\Unit\Traits;

/**
 * Trait for enum contract testing.
 *
 * Verifies that enum cases and values remain stable across releases.
 */
trait EnumContractTestTrait {

  /**
   * Asserts an enum has exactly the expected case names.
   *
   * @param string $enum
   *   Fully qualified enum class name.
   * @param array<string> $expectedCases
   *   Expected case names.
   */
  protected function assertEnumHasCases(string $enum, array $expectedCases): void {
    $ref = new \ReflectionEnum($enum);
    $actualCases = array_map(
      fn(\ReflectionEnumUnitCase $c): string => $c->getName(),
      $ref->getCases()
    );
    sort($actualCases);
    sort($expectedCases);
    $this->assertEquals($expectedCases, $actualCases, "Enum {$enum} cases mismatch");
  }

  /**
   * Asserts a backed enum has exactly the expected name => value mapping.
   *
   * @param string $enum
   *   Fully qualified enum class name.
   * @param array<string, string|int> $expectedValues
   *   Map of case name => backed value.
   */
  protected function assertBackedEnumValues(string $enum, array $expectedValues): void {
    $ref = new \ReflectionEnum($enum);
    $this->assertTrue($ref->isBacked(), "Enum {$enum} must be a backed enum");

    foreach ($expectedValues as $caseName => $expectedValue) {
      $case = $ref->getCase($caseName);
      $this->assertInstanceOf(\ReflectionEnumBackedCase::class, $case);
      $this->assertEquals(
        $expectedValue,
        $case->getBackingValue(),
        "Enum {$enum}::{$caseName} value mismatch"
      );
    }

    // Ensure no extra cases exist.
    $this->assertCount(
      count($expectedValues),
      $ref->getCases(),
      "Enum {$enum} has unexpected extra cases"
    );
  }

  /**
   * Asserts an enum has a specific method.
   *
   * @param string $enum
   *   Fully qualified enum class name.
   * @param string $method
   *   The method name.
   */
  protected function assertEnumHasMethod(string $enum, string $method): void {
    $ref = new \ReflectionEnum($enum);
    $this->assertTrue($ref->hasMethod($method), "Enum {$enum} must have method {$method}()");
  }

}
