<?php

namespace Drupal\Tests\dkan_metastore\Functional\Storage;

use ColinODell\PsrTestLogger\TestLogger;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\File\FileSystem;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Tests\BrowserTestBase;
use Drupal\dkan_metastore\Storage\Data;
use Psr\Log\LoggerInterface;
use org\bovigo\vfs\vfsStream;

/**
 * Test the Data class.
 *
 * Because of the tight coupling and unification of concerns, this is a
 * BrowserTestBase test. A Kernel test would be too complex and fragile.
 *
 * @covers \Drupal\dkan_metastore\Storage\Data
 * @coversDefaultClass \Drupal\dkan_metastore\Storage\Data
 *
 * @group dkan
 * @group metastore
 * @group functional
 * @group btb
 * @group functional2
 */
class DataTest extends BrowserTestBase {

  protected $defaultTheme = 'stark';

  protected static $modules = [
    'dkan_metastore',
    'node',
  ];

  /**
   * Test the logging of htmlPurifier().
   *
   * @covers ::htmlPurifier
   */
  public function testHtmlPurifierLogging() {
    // Set up a read-only temp directory.
    $temp = vfsStream::setup('temp');
    $temp_dir = vfsStream::newDirectory('mytemp', 0000)
      ->at($temp);

    // Tell the file system service to use this temp directory, which will
    // prevent the HTML purifier from writing its cache directory, and it
    // should log this fact.
    $fs = $this->getMockBuilder(FileSystem::class)
      ->disableOriginalConstructor()
      ->onlyMethods(['getTempDirectory'])
      ->getMock();
    $fs->expects($this->any())
      ->method('getTempDirectory')
      ->willReturn($temp_dir->url());

    // Create a Data object with a testable logger.
    $logger = new TestLogger();
    $data = new StubData(
      'dataset',
      $this->container->get('entity_type.manager'),
      $this->container->get('config.factory'),
      $fs,
      $logger
    );

    $uuid = '05aea36e-9e24-452e-9cf9-9727ab90c198';

    // Since filterHtml() and htmlPurifier() are private, we call in from
    // store() with crafted data.
    $data->filterHtml((object) [
      'identifier' => $uuid,
      'title' => 'title',
      'data' => (object) [
        'description' => 'purify me',
      ],
    ]);

    // We logged that the cache directory was not created.
    $this->assertTrue(
      $logger->hasErrorThatContains('Failed to create cache directory for HTML purifier')
    );

  }

}

/**
 * Stub out the abstract Data class with just enough to make it run.
 *
 * Values are copied from NodeData.
 */
class StubData extends Data {

  public function __construct(string $schemaId, EntityTypeManagerInterface $entityTypeManager, ConfigFactoryInterface $config_factory, FileSystemInterface $file_system, LoggerInterface $loggerChannel) {
    $this->entityType = 'node';
    $this->bundle = 'data';
    $this->bundleKey = 'type';
    $this->labelKey = 'title';
    $this->schemaIdField = 'field_data_type';
    $this->metadataField = 'field_json_metadata';
    parent::__construct($schemaId, $entityTypeManager, $config_factory, $file_system, $loggerChannel);
  }

  public function retrieveContains(string $string, bool $caseSensitive): array {
    return [];
  }

  public function retrieveByHash($hash, $schemaId) {
  }

}
