<?php

namespace Drupal\Tests\acquia_contenthub\Kernel\EventSubscriber\HandleWebhook;

use Acquia\Hmac\Key;
use Drupal\acquia_contenthub\Event\HandleWebhookEvent;
use Drupal\acquia_contenthub_publisher\EventSubscriber\HandleWebhook\UpdateMultiplePublishedAssets;
use Drupal\Core\Config\Config;
use Drupal\Core\Database\Connection;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
use Drupal\Tests\acquia_contenthub\Kernel\Traits\AcquiaContentHubAdminSettingsTrait;
use Symfony\Component\HttpFoundation\Request;

/**
 * Tests multiple entity updated published status.
 *
 * @group acquia_contenthub
 *
 * @coversDefaultClass \Drupal\acquia_contenthub_publisher\EventSubscriber\HandleWebhook\UpdateMultiplePublishedAssets
 *
 * @package Drupal\Tests\acquia_contenthub\Kernel\EventSubscriber\HandleWebhook
 */
class UpdateMultiplePublishedTest extends EntityKernelTestBase {

  use AcquiaContentHubAdminSettingsTrait;

  /**
   * Update published instance.
   *
   * @var \Drupal\acquia_contenthub_publisher\EventSubscriber\HandleWebhook\UpdateMultiplePublishedAssets
   */
  protected UpdateMultiplePublishedAssets $updateMultiplePublishedAssets;

  /**
   * Content Hub Client Factory.
   *
   * @var \Drupal\acquia_contenthub\Client\ClientFactory|\Drupal\acquia_contenthub_server_test\Client\ClientFactoryMock
   */
  protected $clientFactory;

  /**
   * Config object.
   *
   * @var \Drupal\Core\Config\Config
   */
  protected Config $configFactory;

  /**
   * Database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected Connection $database;

  /**
   * A test node.
   *
   * @var \Drupal\node\NodeInterface
   */
  protected NodeInterface $node;

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

  /**
   * {@inheritDoc}
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  protected function setUp(): void {
    parent::setUp();

    $this->installSchema('acquia_contenthub_publisher', ['acquia_contenthub_publisher_export_tracking']);

    $this->createAcquiaContentHubAdminSettings();
    $this->clientFactory = $this->container->get('acquia_contenthub.client.factory');

    // Create a test node.
    $this->node = Node::create([
      'type' => 'article',
      'title' => 'Test EN',
      'uuid' => '98213529-0000-0001-0000-123456789123',
    ]);
    $this->node->save();

    // Create another test node.
    $node = Node::create([
      'type' => 'article',
      'title' => 'Test Node',
      'uuid' => '98213529-0000-0001-0000-123456789124',
    ]);
    $node->save();

    $this->database = $this->container->get('database');
    $this->updateMultiplePublishedAssets = new UpdateMultiplePublishedAssets($this->database);
  }

  /**
   * Tests entity updated status for webhook V2.
   *
   * @param mixed $args
   *   Data.
   *
   * @dataProvider webhookV2DataProvider
   *
   * @throws \ReflectionException
   */
  public function testUpdatePublishedWebhookV2(...$args): void {
    $key = new Key('id', 'secret');
    $request = Request::createFromGlobals();

    $client = $this->clientFactory->getClient();

    $payload = [
      'crud' => 'update',
      'status' => 'successful',
      'assets' => [
        [
          'type' => $args[0][0],
          'uuid' => $args[0][1],
          'origin' => $client->getSettings()->getUuid(),
        ],
        [
          'type' => $args[1][0],
          'uuid' => $args[1][1],
          'origin' => $client->getSettings()->getUuid(),
        ],
      ],
    ];
    $event = new HandleWebhookEvent($request, $payload, $key, $client, TRUE);
    $this->updateMultiplePublishedAssets->onHandleWebhook($event);

    $entity_status = $this->getStatusByUuid($args[0][1]);
    $this->assertEquals($entity_status, $args[0][2]);
    $entity_status = $this->getStatusByUuid($args[1][1]);
    $this->assertEquals($entity_status, $args[1][2]);
  }

  /**
   * Tests entity updated status with empty origin.
   */
  public function testUpdatePublishedWithEmptyOrigin(): void {
    $key = new Key('id', 'secret');
    $request = Request::createFromGlobals();

    $client = $this->clientFactory->getClient();

    $payload = [
      'crud' => 'update',
      'status' => 'successful',
      'assets' => [
        [
          'type' => 'drupal8_content_entity',
          'uuid' => '98213529-0000-0001-0000-123456789123',
          'origin' => '',
        ],
      ],
    ];
    $event = new HandleWebhookEvent($request, $payload, $key, $client, TRUE);
    $this->updateMultiplePublishedAssets->onHandleWebhook($event);

    $entity_status = $this->getStatusByUuid('98213529-0000-0001-0000-123456789123');
    $this->assertEquals($entity_status, 'queued');
  }

  /**
   * Data provider for testUpdatePublished webhook v2.
   */
  public static function webhookV2DataProvider(): array {
    return [
      [
        [
          'test_entity',
          '',
          '',
        ],
        [
          'test_entity',
          '',
          '',
        ],
      ],
      [
        [
          'drupal8_content_entity',
          '98213529-0000-0001-0000-123456789123',
          'confirmed',
        ],
        [
          'drupal8_content_entity',
          '98213529-0000-0001-0000-123456789124',
          'confirmed',
        ],
      ],
    ];
  }

  /**
   * Fetch entity status.
   *
   * @param string $uuid
   *   Entity uuid.
   *
   * @return string
   *   Export status.
   */
  protected function getStatusByUuid(string $uuid): string {
    return $this->database->select('acquia_contenthub_publisher_export_tracking', 'acpet')
      ->fields('acpet', ['status'])
      ->condition('acpet.entity_uuid', $uuid)
      ->execute()
      ->fetchField();
  }

}
