<?php

namespace Drupal\Tests\eb\Traits;

use Drupal\node\Entity\NodeType;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\user\Entity\Role;

/**
 * Provides helper methods for creating bundles in tests.
 */
trait BundleCreationTrait {

  /**
   * Creates a node type.
   *
   * @param string $type
   *   The node type machine name.
   * @param string $name
   *   The human-readable name.
   * @param array<string, mixed> $values
   *   Additional values.
   *
   * @return \Drupal\node\Entity\NodeType
   *   The created node type.
   */
  protected function createTestNodeType(string $type, string $name, array $values = []): NodeType {
    $nodeType = NodeType::create([
      'type' => $type,
      'name' => $name,
      'description' => $values['description'] ?? "Test node type: $name",
    ] + $values);
    $nodeType->save();
    return $nodeType;
  }

  /**
   * Creates a taxonomy vocabulary.
   *
   * @param string $vid
   *   The vocabulary machine name.
   * @param string $name
   *   The human-readable name.
   * @param array<string, mixed> $values
   *   Additional values.
   *
   * @return \Drupal\taxonomy\Entity\Vocabulary
   *   The created vocabulary.
   */
  protected function createTestVocabulary(string $vid, string $name, array $values = []): Vocabulary {
    $vocabulary = Vocabulary::create([
      'vid' => $vid,
      'name' => $name,
      'description' => $values['description'] ?? "Test vocabulary: $name",
    ] + $values);
    $vocabulary->save();
    return $vocabulary;
  }

  /**
   * Creates a user role.
   *
   * @param string $id
   *   The role machine name.
   * @param string $label
   *   The human-readable label.
   * @param array<string> $permissions
   *   Permissions to grant.
   *
   * @return \Drupal\user\Entity\Role
   *   The created role.
   */
  protected function createTestRole(string $id, string $label, array $permissions = []): Role {
    $role = Role::create([
      'id' => $id,
      'label' => $label,
    ]);
    $role->save();

    if ($permissions) {
      foreach ($permissions as $permission) {
        $role->grantPermission($permission);
      }
      $role->save();
    }

    return $role;
  }

  /**
   * Asserts that a node type exists with expected properties.
   *
   * @param string $type
   *   The node type machine name.
   * @param array<string, mixed> $expected
   *   Expected properties (label, description, etc.).
   */
  protected function assertNodeTypeProperties(string $type, array $expected = []): void {
    $nodeType = NodeType::load($type);
    $this->assertNotNull($nodeType, "Node type '$type' should exist.");

    if (isset($expected['label'])) {
      $this->assertEquals($expected['label'], $nodeType->label(), "Node type label should match.");
    }

    if (isset($expected['description'])) {
      $this->assertEquals($expected['description'], $nodeType->getDescription(), "Node type description should match.");
    }
  }

  /**
   * Asserts that a vocabulary exists with expected properties.
   *
   * @param string $vid
   *   The vocabulary machine name.
   * @param array<string, mixed> $expected
   *   Expected properties.
   */
  protected function assertVocabularyProperties(string $vid, array $expected = []): void {
    $vocabulary = Vocabulary::load($vid);
    $this->assertNotNull($vocabulary, "Vocabulary '$vid' should exist.");

    if (isset($expected['label'])) {
      $this->assertEquals($expected['label'], $vocabulary->label(), "Vocabulary label should match.");
    }

    if (isset($expected['description'])) {
      $this->assertEquals($expected['description'], $vocabulary->getDescription(), "Vocabulary description should match.");
    }
  }

  /**
   * Asserts that a role exists with specific permissions.
   *
   * @param string $id
   *   The role machine name.
   * @param array<string> $expectedPermissions
   *   Expected permissions.
   */
  protected function assertRolePermissions(string $id, array $expectedPermissions): void {
    $role = Role::load($id);
    $this->assertNotNull($role, "Role '$id' should exist.");

    foreach ($expectedPermissions as $permission) {
      $this->assertTrue($role->hasPermission($permission), "Role should have permission: $permission");
    }
  }

  /**
   * Deletes a node type if it exists.
   *
   * @param string $type
   *   The node type machine name.
   */
  protected function deleteNodeType(string $type): void {
    $nodeType = NodeType::load($type);
    if ($nodeType) {
      $nodeType->delete();
    }
  }

  /**
   * Deletes a vocabulary if it exists.
   *
   * @param string $vid
   *   The vocabulary machine name.
   */
  protected function deleteVocabulary(string $vid): void {
    $vocabulary = Vocabulary::load($vid);
    if ($vocabulary) {
      $vocabulary->delete();
    }
  }

  /**
   * Deletes a role if it exists.
   *
   * @param string $id
   *   The role machine name.
   */
  protected function deleteRole(string $id): void {
    $role = Role::load($id);
    if ($role) {
      $role->delete();
    }
  }

}
