<?php

declare(strict_types=1);

namespace Drupal\Tests\flowdrop\Unit\Traits;

/**
 * Trait for reflection-based interface contract testing.
 *
 * Verifies that interface method signatures remain stable across releases.
 */
trait InterfaceContractTestTrait {

  /**
   * Asserts an interface has a method with expected parameter names.
   *
   * @param string $interface
   *   Fully qualified interface name.
   * @param string $method
   *   The method name.
   * @param array<string> $expectedParams
   *   Expected parameter names in order.
   */
  protected function assertInterfaceHasMethod(string $interface, string $method, array $expectedParams = []): void {
    $ref = new \ReflectionClass($interface);
    $this->assertTrue($ref->hasMethod($method), "Interface {$interface} must have method {$method}()");

    if ($expectedParams !== []) {
      $refMethod = $ref->getMethod($method);
      $actualParams = array_map(
        fn(\ReflectionParameter $p): string => $p->getName(),
        $refMethod->getParameters()
      );
      $this->assertEquals($expectedParams, $actualParams, "Method {$method}() parameter names mismatch");
    }
  }

  /**
   * Asserts an interface has exactly the expected number of methods.
   *
   * @param string $interface
   *   Fully qualified interface name.
   * @param int $count
   *   Expected number of methods.
   */
  protected function assertInterfaceMethodCount(string $interface, int $count): void {
    $ref = new \ReflectionClass($interface);
    $methods = $ref->getMethods(\ReflectionMethod::IS_PUBLIC);
    $this->assertCount($count, $methods, "Interface {$interface} method count mismatch");
  }

  /**
   * Asserts an interface extends a parent interface.
   *
   * @param string $interface
   *   Fully qualified interface name.
   * @param string $parent
   *   Expected parent interface.
   */
  protected function assertInterfaceExtends(string $interface, string $parent): void {
    $ref = new \ReflectionClass($interface);
    $this->assertTrue(
      $ref->isSubclassOf($parent) || in_array($parent, $ref->getInterfaceNames(), TRUE),
      "Interface {$interface} must extend {$parent}"
    );
  }

}
