<?php

namespace Drupal\Tests\eb\Functional;

use Drupal\node\Entity\NodeType;
use Drupal\Tests\BrowserTestBase;

/**
 * Tests the Entity Builder export form.
 *
 * @group eb
 */
class ExportFormTest extends BrowserTestBase {

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

  /**
   * {@inheritdoc}
   */
  protected static $modules = ['eb', 'node', 'field', 'field_ui', 'user'];

  /**
   * A user with permission to use entity builder.
   *
   * @var \Drupal\user\UserInterface
   */
  protected $adminUser;

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

    // Create a user with export permissions.
    $this->adminUser = $this->drupalCreateUser([
      'export entity architecture',
      'administer entity builder',
    ]);

    // Create a test content type.
    NodeType::create([
      'type' => 'test_article',
      'name' => 'Test Article',
      'description' => 'A test article type',
    ])->save();
  }

  /**
   * Tests access to the export form.
   */
  public function testExportFormAccess(): void {
    // Anonymous users should not have access.
    $this->drupalGet('/admin/config/development/eb/export');
    $this->assertSession()->statusCodeEquals(403);

    // Authenticated users without permission should not have access.
    $user = $this->drupalCreateUser();
    $this->drupalLogin($user);
    $this->drupalGet('/admin/config/development/eb/export');
    $this->assertSession()->statusCodeEquals(403);

    // Admin user should have access.
    $this->drupalLogin($this->adminUser);
    $this->drupalGet('/admin/config/development/eb/export');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('Select Bundles to Export');
  }

  /**
   * Tests the export form elements.
   */
  public function testExportFormElements(): void {
    $this->drupalLogin($this->adminUser);
    $this->drupalGet('/admin/config/development/eb/export');

    // Check that definition settings are present.
    $this->assertSession()->pageTextContains('Definition Settings');
    $this->assertSession()->fieldExists('definition_label');
    $this->assertSession()->fieldExists('definition_id');

    // Check that entity type sections are present.
    $this->assertSession()->pageTextContains('Content');

    // Check that our test bundle is available.
    $this->assertSession()->pageTextContains('Test Article');

    // Check export options are present.
    $this->assertSession()->fieldExists('options[include_fields]');
    $this->assertSession()->fieldExists('options[include_displays]');
    $this->assertSession()->fieldExists('options[include_extensions]');
    $this->assertSession()->fieldExists('options[normalize_settings]');

    // Check submit button.
    $this->assertSession()->buttonExists('Generate Definition');
  }

  /**
   * Tests validation when no bundles are selected.
   */
  public function testExportFormNoSelectionValidation(): void {
    $this->drupalLogin($this->adminUser);
    $this->drupalGet('/admin/config/development/eb/export');

    // Submit without selecting any bundles.
    $edit = [
      'definition_label' => 'Test Definition',
      'definition_id' => 'test_definition',
      'options[include_fields]' => TRUE,
    ];

    $this->submitForm($edit, 'Generate Definition');

    // Should show validation error.
    $this->assertSession()->pageTextContains('Please select at least one bundle to export');
  }

  /**
   * Tests generating a definition from bundle.
   */
  public function testExportBundleGeneratesDefinition(): void {
    $this->drupalLogin($this->adminUser);
    $this->drupalGet('/admin/config/development/eb/export');

    // Select the test article bundle and generate definition.
    $edit = [
      'definition_label' => 'Test Export Definition',
      'definition_id' => 'test_export_definition',
      'node[bundles][test_article]' => TRUE,
      'options[include_fields]' => TRUE,
      'options[include_displays]' => TRUE,
      'options[include_extensions]' => TRUE,
    ];

    $this->submitForm($edit, 'Generate Definition');

    // Should redirect to definition list with success message.
    $this->assertSession()->pageTextContains('Definition');
  }

  /**
   * Tests the select all functionality.
   */
  public function testExportFormSelectAll(): void {
    // Create multiple content types.
    NodeType::create([
      'type' => 'page',
      'name' => 'Basic Page',
    ])->save();

    NodeType::create([
      'type' => 'news',
      'name' => 'News',
    ])->save();

    $this->drupalLogin($this->adminUser);
    $this->drupalGet('/admin/config/development/eb/export');

    // The select all checkbox should be present.
    $this->assertSession()->fieldExists('node[select_all]');
  }

}
