<?php

namespace Drupal\Tests\eb\Functional;

use Drupal\Core\File\FileSystemInterface;
use Drupal\Tests\BrowserTestBase;

/**
 * Tests the Entity Builder import form.
 *
 * @group eb
 */
class ImportFormTest extends BrowserTestBase {

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

  /**
   * {@inheritdoc}
   */
  protected static $modules = ['eb', 'node', 'field', 'file', '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 import permissions.
    $this->adminUser = $this->drupalCreateUser([
      'import entity architecture',
      'administer entity builder',
    ]);
  }

  /**
   * Creates a test file with the given content and extension.
   *
   * @param string $filename
   *   The filename including extension.
   * @param string $content
   *   The file content.
   *
   * @return string
   *   The real path to the created file.
   */
  protected function createTestFile(string $filename, string $content): string {
    $directory = 'public://eb_test_files';
    \Drupal::service('file_system')->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY);
    $file_path = $directory . '/' . $filename;
    file_put_contents($file_path, $content);
    return \Drupal::service('file_system')->realpath($file_path);
  }

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

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

    // Admin user should have access.
    $this->drupalLogin($this->adminUser);
    $this->drupalGet('/admin/config/development/eb/import');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('Upload an entity architecture definition file');
  }

  /**
   * Tests the upload step of the import form.
   */
  public function testImportFormUploadStep(): void {
    $this->drupalLogin($this->adminUser);
    $this->drupalGet('/admin/config/development/eb/import');

    // Check that form elements are present.
    $this->assertSession()->fieldExists('files[file]');
    $this->assertSession()->fieldExists('execute_immediately');
    $this->assertSession()->fieldExists('force_overwrite');
    $this->assertSession()->buttonExists('Upload and Validate');
  }

  /**
   * Tests uploading a valid YAML file.
   */
  public function testImportFormValidYamlUpload(): void {
    $this->drupalLogin($this->adminUser);

    // Create a temporary YAML file with definition format.
    $yaml_content = <<<YAML
id: test_import
label: Test Import Definition
bundle_definitions:
  - entity_type: node
    bundle_id: test_article
    label: Test Article
    description: A test article bundle
YAML;

    $file_path = $this->createTestFile('test_import.yml', $yaml_content);

    // Upload the file.
    $edit = [
      'files[file]' => $file_path,
    ];

    $this->drupalGet('/admin/config/development/eb/import');
    $this->submitForm($edit, 'Upload and Validate');

    // The form should not show parsing errors for valid YAML.
    $this->assertSession()->pageTextNotContains('Error parsing file');
  }

  /**
   * Tests uploading an invalid file extension.
   */
  public function testImportFormInvalidFileUpload(): void {
    $this->drupalLogin($this->adminUser);

    // Create a file with invalid extension.
    $file_path = $this->createTestFile('test_import.txt', 'invalid content');

    $edit = [
      'files[file]' => $file_path,
    ];

    $this->drupalGet('/admin/config/development/eb/import');
    $this->submitForm($edit, 'Upload and Validate');

    // Should show an error - either from FileExtension validator or form.
    $this->assertSession()->statusMessageExists('error');
    // Should remain on the import form, not redirected to confirm.
    $this->assertSession()->addressMatches('/\/admin\/config\/development\/eb\/import/');
  }

  /**
   * Tests uploading an empty file.
   */
  public function testImportFormEmptyFileUpload(): void {
    $this->drupalLogin($this->adminUser);

    // Create an empty file.
    $file_path = $this->createTestFile('test_import_empty.yml', '');

    $edit = [
      'files[file]' => $file_path,
    ];

    $this->drupalGet('/admin/config/development/eb/import');
    $this->submitForm($edit, 'Upload and Validate');

    // Should show an error - either from empty file validation or form.
    // Empty files may be rejected by Drupal's upload handler or our validation.
    $this->assertSession()->statusMessageExists('error');
    // Should remain on the import form, not redirected to confirm.
    $this->assertSession()->addressMatches('/\/admin\/config\/development\/eb\/import/');
  }

  /**
   * Tests the form with malformed YAML.
   */
  public function testImportFormMalformedYaml(): void {
    $this->drupalLogin($this->adminUser);

    // Create a file with malformed YAML (unclosed quote).
    $yaml_content = "id: \"test_malformed\nbundle_definitions:\n  - invalid yaml here: [";

    $file_path = $this->createTestFile('test_malformed.yml', $yaml_content);

    $edit = [
      'files[file]' => $file_path,
    ];

    $this->drupalGet('/admin/config/development/eb/import');
    $this->submitForm($edit, 'Upload and Validate');

    // Should show parsing error from YAML parser or validation error.
    $this->assertSession()->pageTextMatches('/Error parsing file|valid file|error/i');
  }

}
