<?php

namespace Drupal\Tests\acquia_contenthub_publisher\Kernel;

use Drupal\acquia_contenthub_publisher\Plugin\views\field\EntityBulkForm;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\Tests\acquia_contenthub\Kernel\Traits\AcquiaContentHubAdminSettingsTrait;
use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
use Prophecy\PhpUnit\ProphecyTrait;

/**
 * Tests CH add to export queue bulk operation.
 *
 * @group acquia_contenthub_publisher
 *
 * @requires module depcalc
 *
 * @coversDefaultClass \Drupal\acquia_contenthub_publisher\Plugin\views\field\EntityBulkForm
 */
class AddEntitiesToExportQueueInBulkTest extends EntityKernelTestBase {

  use AcquiaContentHubAdminSettingsTrait;
  use ContentTypeCreationTrait;
  use MessengerTrait;
  use ProphecyTrait;

  /**
   * An entity.
   *
   * @var \Drupal\Core\Entity\EntityInterface
   */
  protected EntityInterface $entity;

  /**
   * CH entity bulk form.
   *
   * @var \Drupal\acquia_contenthub_publisher\Plugin\views\field\EntityBulkForm
   */
  protected EntityBulkForm $bulkForm;

  /**
   * The form state.
   *
   * @var \Drupal\Core\Form\FormStateInterface
   */
  protected FormStateInterface $formState;

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'node',
    'depcalc',
    'acquia_contenthub',
    'acquia_contenthub_publisher',
  ];

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

    $this->installSchema('acquia_contenthub_publisher', ['acquia_contenthub_publisher_export_tracking']);
    $this->createAcquiaContentHubAdminSettings();
    $this->installConfig('node');

    /** @var \Drupal\acquia_contenthub_publisher\Libs\ExportSettingsInterface $export_settings */
    $export_settings = $this->container->get('acquia_contenthub_publisher.export_settings');
    $export_settings->toggleManualExportMode(TRUE);
    $export_settings->save();

    $this->createContentType([
      'type' => 'article',
    ])->save();
    $this->entity = Node::create([
      'type' => 'article',
      'title' => 'Test Node',
    ]);
    $this->entity->save();

    $this->bulkForm = new EntityBulkForm(
      [
        'id' => 'ch_bulk_form',
      ],
      'ch_bulk_form',
      [
        'plugin_type' => 'field',
        'id' => 'ch_bulk_form',
        'class' => 'Drupal\acquia_contenthub_publisher\Plugin\views\field\EntityBulkForm',
        'provider' => 'acquia_contenthub_publisher',
      ],
      $this->container->get('entity_type.manager'),
      $this->container->get('language_manager'),
      $this->container->get('messenger'),
      $this->container->get('entity.repository'),
      $this->container->get('acquia_contenthub_publisher.entity_enqueuer'),
      $this->container->get('acquia_contenthub.configuration'),
      $this->container->get('acquia_contenthub.logger_channel'),
      $this->container->get('cache.depcalc'),
      $this->container->get('acquia_contenthub_publisher.tracker'),
      $this->container->get('current_route_match'),
    );
    $this->bulkForm->options = [
      'id' => 'ch_bulk_form',
    ];
    $this->formState = new FormState();
    $this->formState->set('step', 'views_form_views_form');
  }

  /**
   * Tests select and enqueue single entity.
   */
  public function testSelectAndEnqueueSingleEntity(): void {
    $selected = [
      $this->getBulkFormKey($this->entity),
    ];
    $user_input = [
      'ch_bulk_form' => $selected,
    ];
    $this->formState->setUserInput($user_input);
    $form = [];
    $this->messenger()->deleteAll();

    $this->bulkForm->viewsFormSubmit($form, $this->formState);
    $messages = $this->messenger()->all();
    $this->assertArrayHasKey(MessengerInterface::TYPE_STATUS, $messages);
    $this->assertSame('1 entity enqueued.', $messages[MessengerInterface::TYPE_STATUS][0]->__toString());
  }

  /**
   * Tests select and enqueue multiple entities.
   */
  public function testSelectAndEnqueueMultipleEntity(): void {
    $field_config_entity = $this->entityTypeManager->getStorage('field_config')->load('node.article.body');
    $entity_view_display_config_entity = $this->entityTypeManager->getStorage('entity_view_display')->load('node.article.teaser');
    $selected = [
      $this->getBulkFormKey($this->entity),
      $this->getBulkFormKey($field_config_entity),
      $this->getBulkFormKey($entity_view_display_config_entity),
    ];
    $user_input = [
      'ch_bulk_form' => $selected,
    ];
    $this->formState->setUserInput($user_input);
    $form = [];
    $this->messenger()->deleteAll();

    $this->bulkForm->viewsFormSubmit($form, $this->formState);
    $messages = $this->messenger()->all();
    $this->assertArrayHasKey(MessengerInterface::TYPE_STATUS, $messages);
    $this->assertSame('3 entities enqueued.', $messages[MessengerInterface::TYPE_STATUS][0]->__toString());

    // Testing ineligible entities.
    $selected = [
      $this->getBulkFormKey($this->entity),
      $this->getBulkFormKey($field_config_entity),
    ];
    $user_input = [
      'ch_bulk_form' => $selected,
    ];
    $this->formState->setUserInput($user_input);
    $form = [];
    $this->messenger()->deleteAll();

    $this->bulkForm->viewsFormSubmit($form, $this->formState);
    $messages = $this->messenger()->all();
    $this->assertArrayHasKey(MessengerInterface::TYPE_WARNING, $messages);
    $expected = '2 ineligible entities were skipped. <a href="https://docs.acquia.com/acquia-cms/add-ons/content-hub/manage/developing/eligibile-and-ineligible-entities">Know more</a>';
    $this->assertSame($expected, $messages[MessengerInterface::TYPE_WARNING][0]->__toString());

    // Testing eligible and ineligible entities.
    $entity_form_display_config_entity = $this->entityTypeManager->getStorage('entity_form_display')->load('node.article.default');
    $selected = [
      $this->getBulkFormKey($this->entity),
      $this->getBulkFormKey($entity_form_display_config_entity),
    ];
    $user_input = [
      'ch_bulk_form' => $selected,
    ];
    $this->formState->setUserInput($user_input);
    $form = [];
    $this->messenger()->deleteAll();

    $this->bulkForm->viewsFormSubmit($form, $this->formState);
    $messages = $this->messenger()->all();
    $this->assertArrayHasKey(MessengerInterface::TYPE_STATUS, $messages);
    $this->assertArrayHasKey(MessengerInterface::TYPE_WARNING, $messages);
    $this->assertSame('1 entity enqueued.', $messages[MessengerInterface::TYPE_STATUS][0]->__toString());
    $warning_message = array_pop($messages[MessengerInterface::TYPE_WARNING]);
    $expected = '1 ineligible entity was skipped. <a href="https://docs.acquia.com/acquia-cms/add-ons/content-hub/manage/developing/eligibile-and-ineligible-entities">Know more</a>';
    $this->assertSame($expected, $warning_message->__toString());

  }

  /**
   * The bulk form key.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   Entity.
   *
   * @return string
   *   Base64 encoded entity type and entity id.
   */
  protected function getBulkFormKey(EntityInterface $entity): string {
    return base64_encode(json_encode([$entity->getEntityTypeId(), $entity->id()]));
  }

}
