<?php

namespace Drupal\Tests\acquia_contenthub_subscriber\Kernel\EventSubscriber\ParseCdf;

use Acquia\ContentHubClient\CDF\CDFObject;
use Drupal\acquia_contenthub\Event\ParseCdfEntityEvent;
use Drupal\acquia_contenthub_subscriber\EventSubscriber\ParseCdf\ViewFiltersParseCdfHandler;
use Drupal\depcalc\DependencyStack;
use Drupal\KernelTests\KernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\taxonomy\Entity\Term;
use Drupal\Tests\acquia_contenthub\Kernel\Traits\AssetHandlerTrait;
use Drupal\Tests\acquia_contenthub\Kernel\Traits\CdfDocumentCreatorTrait;
use Drupal\Tests\acquia_contenthub\Kernel\Traits\FieldTrait;

/**
 * Tests view filters parse cdf handler.
 *
 * @group acquia_contenthub_subscriber
 * @coversDefaultClass \Drupal\acquia_contenthub_subscriber\EventSubscriber\ParseCdf\ViewFiltersParseCdfHandler
 *
 * @requires module depcalc
 *
 * @package Drupal\Tests\acquia_contenthub_subscriber\Kernel\EventSubscriber\ParseCdf
 */
class ViewFiltersParseCdfHandlerTest extends KernelTestBase {

  use AssetHandlerTrait, FieldTrait, CdfDocumentCreatorTrait {
    AssetHandlerTrait::attachZipExtension insteadof CdfDocumentCreatorTrait;
  }

  /**
   * Term UUID.
   */
  protected const TERM_UUID = 'f40a56ad-b4de-4138-86ac-08d9d9c96745';

  /**
   * Node UUID.
   */
  protected const NODE_UUID = '1fd5e450-dd1f-466a-a000-65899d184716';

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'acquia_contenthub',
    'acquia_contenthub_subscriber',
    'depcalc',
    'user',
    'field',
    'filter',
    'node',
    'text',
    'system',
    'taxonomy',
  ];

  /**
   * Event dispatcher.
   *
   * @var \Symfony\Component\EventDispatcher\EventDispatcher
   */
  protected $dispatcher;

  /**
   * ViewFiltersParseCdfHandler object.
   *
   * @var \Drupal\acquia_contenthub_subscriber\EventSubscriber\ParseCdf\ViewFiltersParseCdfHandler
   */
  protected $cdfHandler;

  /**
   * Term entity.
   *
   * @var \Drupal\taxonomy\TermInterface
   */
  protected $term;

  /**
   * Node entity.
   *
   * @var \Drupal\node\NodeInterface
   */
  protected $node;

  /**
   * {@inheritdoc}
   *
   * @throws \Exception
   */
  protected function setUp() : void {
    parent::setUp();
    $this->installEntitySchema('user');
    $this->installEntitySchema('node');
    $this->installEntitySchema('taxonomy_term');
    $this->installConfig([
      'field',
      'filter',
      'node',
    ]);
    $this->dispatcher = $this->container->get('event_dispatcher');
    $this->cdfHandler = new ViewFiltersParseCdfHandler(
      $this->container->get('event_dispatcher')
    );

    $this->term = Term::create([
      'vid' => 'tags',
      'name' => 'tag1',
      'uuid' => self::TERM_UUID,
      'tid' => '3',
    ]);
    $this->term->save();

    NodeType::create([
      'type' => 'test',
    ])->save();

    // Create field field_basic_content_type of entity_reference field type.
    $field_storage = $this->createFieldStorage(
      'field_basic_content_type',
      'node',
      'entity_reference',
      [
        'target_type' => 'node',
      ]
    );
    $this->createFieldConfig(
      $field_storage,
      'test'
    );

    // Create field field_age of integer field type.
    $field_storage = $this->createFieldStorage(
      'field_age',
      'node',
      'integer',
      [
        'target_type' => 'node',
      ]
    );
    $this->createFieldConfig(
      $field_storage,
      'test'
    );

    $this->node = Node::create([
      'type' => 'test',
      'title' => 'Test Node.',
      'nid' => 7,
      'uuid' => self::NODE_UUID,
    ]);
    $this->node->save();
  }

  /**
   * Tests the ViewFiltersParseCdfHandler.
   */
  public function testOnParseCdf(): void {
    $data = $this->getCdfArray('view-brand-new-view.json');
    $cdf = CDFObject::fromArray($data);
    $metadata = $this->cdfHandler->getDecodedMetadata($cdf);
    // Value for taxonomy_index_tid plugin.
    $term_uuid = $metadata['en']['display']['default']['display_options']['filters']['field_tags_target_id']['value'][0];
    $this->assertSame(self::TERM_UUID, $term_uuid);
    // Value for numeric plugin for entity_reference entity type.
    $node_uuid = $metadata['en']['display']['default']['display_options']['filters']['field_basic_content_type_target_id']['value']['value'];
    $this->assertSame(self::NODE_UUID, $node_uuid);
    // Value for numeric plugin for integer entity type.
    $age_value = $metadata['en']['display']['default']['display_options']['filters']['field_age_value']['value']['value'];
    $this->assertSame('20', $age_value);

    $event = $this->triggerOnParseCdfEvent($cdf);
    $updated_cdf = $event->getCdf();
    $updated_metadata = $this->cdfHandler->getDecodedMetadata($updated_cdf);
    // Updated value for taxonomy_index_tid plugin.
    $term_id = $updated_metadata['en']['display']['default']['display_options']['filters']['field_tags_target_id']['value'][0];
    $this->assertSame($this->term->id(), $term_id);
    // Updated value for numeric plugin for entity_reference field type.
    $node_id = $updated_metadata['en']['display']['default']['display_options']['filters']['field_basic_content_type_target_id']['value']['value'];
    $this->assertSame($this->node->id(), $node_id);
    // Value for numeric plugin for integer field type.
    $age_value = $metadata['en']['display']['default']['display_options']['filters']['field_age_value']['value']['value'];
    $this->assertSame('20', $age_value);
  }

  /**
   * Tests when view filter plugin_id is null.
   */
  public function testNullPluginId(): void {
    $data = $this->getCdfArray('view-brand-new-view.json');
    $cdf = CDFObject::fromArray($data);
    $decoded_metadata = $this->cdfHandler->getDecodedMetadata($cdf);
    $decoded_metadata['en']['display']['default']['display_options']['filters']['field_tags_target_id']['plugin_id'] = NULL;
    $metadata['data'] = base64_encode(json_encode($decoded_metadata));
    $cdf->setMetadata($metadata);
    $event = $this->triggerOnParseCdfEvent($cdf);
    $updated_cdf = $event->getCdf();
    $updated_metadata = $this->cdfHandler->getDecodedMetadata($updated_cdf);

    $term_uuid = $updated_metadata['en']['display']['default']['display_options']['filters']['field_tags_target_id']['value'][0];
    $this->assertSame(self::TERM_UUID, $term_uuid);
  }

  /**
   * Triggers PARSE_CDF event.
   *
   * @param \Acquia\ContentHubClient\CDF\CDFObject $cdf
   *   The CDF to pass to the event.
   *
   * @return \Drupal\acquia_contenthub\Event\ParseCdfEntityEvent
   *   The dispatched event object.
   *
   * @throws \Exception
   */
  protected function triggerOnParseCdfEvent(CDFObject $cdf): ParseCdfEntityEvent {
    $event = new ParseCdfEntityEvent($cdf, new DependencyStack());
    $this->cdfHandler->onParseCdf($event);
    return $event;
  }

}
