<?php

namespace Drupal\Tests\acquia_contenthub_subscriber\Functional;

use Drupal\acquia_contenthub\Settings\ConnectionDetailsInterface;
use Drupal\Tests\acquia_contenthub\Kernel\Traits\AcquiaContentHubAdminSettingsTrait;
use Drupal\Tests\BrowserTestBase;

/**
 * Tests ContentHubPurgeQueueConfirmForm functionality in browser.
 *
 * @coversDefaultClass \Drupal\acquia_contenthub_subscriber\Form\ContentHubPurgeQueueConfirmForm
 *
 * @group acquia_contenthub_subscriber
 *
 * @package Drupal\Tests\acquia_contenthub_subscriber\Functional
 */
class ContentHubPurgeQueueConfirmFormTest extends BrowserTestBase {

  use AcquiaContentHubAdminSettingsTrait;

  /**
   * Path to the purge queue confirmation form.
   */
  const PURGE_QUEUE_FORM_PATH = '/admin/config/services/acquia-contenthub/import-queue/purge-queue-confirm';

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'acquia_contenthub',
    'acquia_contenthub_subscriber',
    'acquia_contenthub_test',
    'acquia_contenthub_server_test',
    'node',
    'user',
  ];

  /**
   * Content Hub administrator user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $authorizedUser;

  /**
   * Unauthorized user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $unauthorizedUser;

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

    $this->createAcquiaContentHubAdminSettings();

    /** @var \Drupal\acquia_contenthub\Settings\ContentHubConfigurationInterface $ach_configuration */
    $ach_configuration = $this->container->get('acquia_contenthub.configuration');
    $ach_configuration->getContentHubConfig()->disableContentHubUpdates();

    $this->authorizedUser = $this->drupalCreateUser([
      'administer acquia content hub',
    ]);

    $this->unauthorizedUser = $this->drupalCreateUser();

    $this->drupalLogin($this->authorizedUser);
  }

  /**
   * Tests form access permissions.
   *
   * @throws \Behat\Mink\Exception\ExpectationException
   * @throws \Behat\Mink\Exception\ResponseTextException
   */
  public function testFormAccessPermissions(): void {
    $session = $this->assertSession();

    $this->drupalGet(self::PURGE_QUEUE_FORM_PATH);
    $session->pageTextContains('Select queue to purge');
    $session->statusCodeEquals(200);

    $this->drupalLogout();
    $this->drupalLogin($this->unauthorizedUser);

    $this->drupalGet(self::PURGE_QUEUE_FORM_PATH);
    $session->pageTextContains('Access denied');
    $session->statusCodeEquals(403);
  }

  /**
   * Tests form rendering with push mode (only local queue).
   *
   * @throws \Behat\Mink\Exception\ExpectationException
   * @throws \Behat\Mink\Exception\ElementNotFoundException
   */
  public function testFormRenderingPushMode(): void {
    $connection_details = $this->container->get('acquia_contenthub.connection_details_config');
    $connection_details->setSyndicationMode(ConnectionDetailsInterface::SYNDICATION_MODE_PUSH);

    $this->drupalLogin($this->authorizedUser);
    $this->drupalGet(self::PURGE_QUEUE_FORM_PATH);

    $session = $this->assertSession();

    $session->statusCodeEquals(200);

    $session->fieldExists('queue_types[local]');
    $session->fieldNotExists('queue_types[service]');

    $session->checkboxChecked('queue_types[local]');

    $session->buttonExists('Confirm');
    $session->buttonExists('Cancel');
  }

  /**
   * Tests form rendering with pull mode (both local and service queues).
   *
   * @throws \Behat\Mink\Exception\ExpectationException
   * @throws \Behat\Mink\Exception\ElementNotFoundException
   */
  public function testFormRenderingPullMode(): void {
    $connection_details = $this->container->get('acquia_contenthub.connection_details_config');
    $connection_details->setSyndicationMode(ConnectionDetailsInterface::SYNDICATION_MODE_PULL);

    $this->drupalLogin($this->authorizedUser);
    $this->drupalGet(self::PURGE_QUEUE_FORM_PATH);

    $session = $this->assertSession();

    $session->fieldExists('queue_types[local]');
    $session->fieldExists('queue_types[service]');

    $session->checkboxNotChecked('queue_types[local]');
    $session->checkboxChecked('queue_types[service]');
  }

  /**
   * Tests successful form submission with local queue purge.
   *
   * @throws \Behat\Mink\Exception\ResponseTextException
   */
  public function testSubmitFormLocalQueuePurge(): void {
    $connection_details = $this->container->get('acquia_contenthub.connection_details_config');
    $connection_details->setSyndicationMode(ConnectionDetailsInterface::SYNDICATION_MODE_PUSH);

    $this->createTestQueueData();

    $this->drupalLogin($this->authorizedUser);
    $this->drupalGet(self::PURGE_QUEUE_FORM_PATH);

    $this->submitForm([
      'queue_types[local]' => 'local',
    ], 'Confirm');

    $session = $this->assertSession();

    $session->pageTextContains('Successfully purged: Local import queue');

    $session->addressEquals('/admin/config/services/acquia-contenthub/import-queue');
  }

  /**
   * Tests form submission with both local and service queue purge in pull mode.
   *
   * @throws \Behat\Mink\Exception\ResponseTextException
   */
  public function testSubmitFormBothQueuesPurge(): void {
    $connection_details = $this->container->get('acquia_contenthub.connection_details_config');
    $connection_details->setSyndicationMode(ConnectionDetailsInterface::SYNDICATION_MODE_PULL);

    $this->createTestQueueData();

    $this->drupalLogin($this->authorizedUser);
    $this->drupalGet(self::PURGE_QUEUE_FORM_PATH);

    $this->submitForm([
      'queue_types[local]' => 'local',
      'queue_types[service]' => 'service',
    ], 'Confirm');

    $session = $this->assertSession();

    $session->pageTextContains('Successfully purged');
    $session->addressEquals('/admin/config/services/acquia-contenthub/import-queue');
  }

  /**
   * Creates test queue data and tracking entries.
   */
  protected function createTestQueueData(): void {
    $this->drupalCreateContentType(['type' => 'article']);
    $node = $this->drupalCreateNode([
      'type' => 'article',
      'title' => 'Test Article',
    ]);

    $queue = \Drupal::queue('acquia_contenthub_subscriber_import');
    $item = new \stdClass();
    $item->uuids = $node->uuid();
    $queue->createItem($item);

    $tracker = $this->container->get('acquia_contenthub_subscriber.tracker');
    $tracker->queue($node->uuid());
  }

}
