<?php

namespace Drupal\Tests\acquia_contenthub_subscriber\Kernel\Libs;

use Drupal\acquia_contenthub_subscriber\Libs\UserDeletionHandler;
use Drupal\acquia_contenthub_subscriber\Libs\UserSyndicationSettingsInterface;
use Drupal\KernelTests\KernelTestBase;
use Drupal\Tests\acquia_contenthub\Unit\Helpers\LoggerMock;
use Drupal\Tests\user\Traits\UserCreationTrait;

/**
 * @coversDefaultClass \Drupal\acquia_contenthub_subscriber\Libs\UserDeletionHandler
 *
 * @group acquia_contenthub_subscriber
 *
 * @requires module depcalc
 */
class UserDeletionHandlerKernelTest extends KernelTestBase {

  use UserCreationTrait;

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'acquia_contenthub',
    'acquia_contenthub_subscriber',
    'depcalc',
    'user',
    'system',
  ];

  /**
   * The SUT.
   *
   * @var \Drupal\acquia_contenthub_subscriber\Libs\UserDeletionHandler
   */
  protected UserDeletionHandler $sut;

  /**
   * User syndication settings.
   *
   * @var \Drupal\acquia_contenthub_subscriber\Libs\UserSyndicationSettingsInterface
   */
  protected UserSyndicationSettingsInterface $userSettings;

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

    $this->installEntitySchema('user');
    $this->installSchema('user', ['users_data']);
    $this->installSchema('system', ['sequences']);

    $this->userSettings = $this->container->get('acquia_contenthub_subscriber.user_syndication.settings');
    $logger_mock = new LoggerMock();
    $this->sut = new UserDeletionHandler($this->userSettings, $logger_mock);
  }

  /**
   * @covers ::blockUser
   *
   * @dataProvider userSettingsDataProvider
   */
  public function testUserDeletionWithDifferentUserSyndicationSettings(bool $user_syndication, string $msg1, string $msg2, bool $block_expectation): void {
    $this->userSettings->toggleUserSyndication($user_syndication);

    $user = $this->createUser();
    $storage = $this->container->get('entity_type.manager')->getStorage('user');
    /** @var \Drupal\user\UserInterface $user */
    $user = $storage->load($user->id());
    $this->assertFalse($user->isBlocked(), $msg1);

    // Reload user.
    /** @var \Drupal\user\UserInterface $user */
    $user = $storage->load($user->id());
    $this->sut->blockUser($user);
    $this->assertEquals($block_expectation, $user->isBlocked(), $msg2);
  }

  /**
   * Provides data for user syndication scenarios.
   *
   * @return array[]
   *   The data on different scenarios.
   */
  public static function userSettingsDataProvider(): array {
    return [
      [
        FALSE,
        'The user, upon initialization, is active.',
        'The user is blocked.',
        TRUE,
      ],
      [
        TRUE,
        'The user, upon initialization, is active.',
        'The user is not blocked, user syndication is disabled.',
        FALSE,
      ],
    ];
  }

  /**
   * @covers ::deleteUserRole
   *
   * @dataProvider userRoleSettingsDataProvider
   */
  public function testUserRoleDeletionWithDifferentUserRoleSyndicationSettings(bool $user_role_syndication, string $msg, bool $role_expectation): void {
    $this->userSettings->toggleUserRoleSyndication($user_role_syndication);

    $role_id = 'custom_role';
    $this->createRole([], $role_id);
    $storage = $this->container->get('entity_type.manager')->getStorage('user_role');
    /** @var \Drupal\user\UserInterface $user */
    $role = $storage->load($role_id);
    $this->sut->deleteUserRole($role);

    $role = $storage->load($role_id);
    $this->assertEquals($role_expectation, is_null($role), $msg);
  }

  /**
   * Provides data for user role syndication scenarios.
   *
   * @return array[]
   *   The data on different scenarios.
   */
  public static function userRoleSettingsDataProvider(): array {
    return [
      [
        FALSE,
        'The user role has been deleted.',
        TRUE,
      ],
      [
        TRUE,
        'The user role has not been deleted, user role syndication is disabled.',
        FALSE,
      ],
    ];
  }

}
