<?php

namespace Drupal\Tests\acquia_contenthub_publisher\Functional;

use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Tests\acquia_contenthub\Kernel\Traits\AcquiaContentHubAdminSettingsTrait;
use Drupal\Tests\BrowserTestBase;
use Drupal\user\UserInterface;

/**
 * Tests Exclude_field settings form elements and interactions.
 *
 * @coversDefaultClass \Drupal\acquia_contenthub_publisher\Form\AcquiaContentHubExcludeFieldsForm
 *
 * @group acquia_contenthub_publisher
 */
class AcquiaContentHubExcludeFieldsFormTest extends BrowserTestBase {

  use AcquiaContentHubAdminSettingsTrait;

  /**
   * Content Hub administrator user.
   *
   * @var \Drupal\user\UserInterface
   */
  protected UserInterface $chUser;

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

  /**
   * Path to Acquia ContentHub Exclude Fields Form.
   */
  const CH_EXCLUDE_FIELDS_FORM_PATH = '/admin/structure/types/manage/news/contenthub';

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

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();
    $this->createAcquiaContentHubAdminSettings();
    $this->chUser = $this->drupalCreateUser([
      'administer acquia content hub',
    ], 'ach_admin');
    $this->drupalLogin($this->chUser);

    $contentType = $this->drupalCreateContentType([
      'type' => 'news',
      'name' => 'News',
    ]);
    $contentType->save();

    // Add a 'body' field to the content type.
    FieldStorageConfig::create([
      'field_name' => 'headline',
      'entity_type' => 'node',
      'type' => 'text',
    ])->save();

    FieldConfig::create([
      'field_name' => 'headline',
      'entity_type' => 'node',
      'bundle' => 'news',
      'label' => 'Headline',
    ])->save();
  }

  /**
   * Tests permissions of different users.
   *
   * @throws \Behat\Mink\Exception\ExpectationException
   * @throws \Behat\Mink\Exception\ResponseTextException
   */
  public function testAcquiaContentHubExcludeFieldsFormPermissions() {
    $session = $this->assertSession();

    $this->drupalGet(self::CH_EXCLUDE_FIELDS_FORM_PATH);
    $session->pageTextContains('Manage Content Hub export');
    $session->statusCodeEquals(200);

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

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

  /**
   * Tests if elements are displayed properly.
   */
  public function testFormUiElements(): void {
    $this->drupalGet(self::CH_EXCLUDE_FIELDS_FORM_PATH);
    $session = $this->assertSession();

    $session->elementExists('css', '#edit-export-table');

    $session->elementTextContains('css', '#edit-export-table thead th:nth-child(1)', 'Fields');
    $session->elementTextContains('css', '#edit-export-table thead th:nth-child(2)', 'Exclude from export');

    $session->elementExists('css', 'tr[data-drupal-selector="edit-export-table-headline"]');

    $checkbox_selector = '#edit-export-table-headline-exclude-from-export';
    $checkbox = $session->elementExists('css', $checkbox_selector);
    $this->assertFalse($checkbox->isChecked(), 'The headline checkbox should not be checked.');

    $checkbox->check();
    $this->getSession()->getPage()->pressButton('Save');
    $session->pageTextContains('Your exclude settings have been saved.');

    $checkbox = $this->getSession()->getPage()->find('css', $checkbox_selector);
    $this->assertTrue($checkbox->isChecked(), 'The headline checkbox should be checked after form submission.');

  }

  /**
   * Tests correct values are saved in exclude_settings config.
   */
  public function testValuesSavedInConfig(): void {
    $this->drupalGet(self::CH_EXCLUDE_FIELDS_FORM_PATH);
    $session = $this->assertSession();

    $config = $this->container->get('config.factory');
    $excluded_fields = $config->get('acquia_contenthub_publisher.exclude_settings')->get('excluded_fields');
    $this->assertEmpty($excluded_fields);

    $session->elementExists('css', '#edit-export-table-headline-exclude-from-export')->check();
    $session->elementExists('css', '#edit-export-table-body-exclude-from-export')->check();
    $session->elementExists('css', '#exclude-fields-save')->click();

    \Drupal::service('cache.config')->invalidateAll();
    $config = $this->container->get('config.factory');
    $excluded_fields = $config->get('acquia_contenthub_publisher.exclude_settings')->get('excluded_fields');
    $this->assertContains('body', $excluded_fields['node']['news']);
    $this->assertContains('headline', $excluded_fields['node']['news']);
  }

}
