<?php

namespace Drupal\Tests\acquia_contenthub\Unit;

use Drupal\acquia_contenthub\Client\ClientFactory;
use Drupal\acquia_contenthub\Controller\ContentHubWebhookController;
use Drupal\Tests\acquia_contenthub\Unit\Helpers\LoggerMock;
use Drupal\Tests\acquia_contenthub\Unit\Helpers\RandomWebhookGeneratorTrait;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Tests ContentHubWebhookController.
 *
 * @group acquia_contenthub
 *
 * @package Drupal\Tests\acquia_contenthub\Unit
 *
 * @coversDefaultClass \Drupal\acquia_contenthub\Controller\ContentHubWebhookController
 */
class WebHookControllerTest extends UnitTestCase {

  use RandomWebhookGeneratorTrait;

  /**
   * The ContentHubWebhookController object to test.
   *
   * @var \Drupal\acquia_contenthub\Controller\ContentHubWebhookController
   */
  protected ContentHubWebhookController $chWebhookController;

  /**
   * The ClientFactory object available to alter.
   *
   * @var \Drupal\acquia_contenthub\Client\ClientFactory|\Prophecy\Prophecy\ObjectProphecy
   */
  protected $clientFactory;

  /**
   * The mocked logger channel.
   *
   * @var \Drupal\Tests\acquia_contenthub\Unit\Helpers\LoggerMock
   */
  protected LoggerMock $loggerMock;

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

    $dispatcher = $this->prophesize(EventDispatcherInterface::class);
    $this->clientFactory = $this->prophesize(ClientFactory::class);
    $this->loggerMock = new LoggerMock();

    $this->chWebhookController = new ContentHubWebhookController(
      $dispatcher->reveal(),
      $this->clientFactory->reveal(),
    );
  }

  /**
   * Validates when payload is empty, response should return 403.
   *
   * @covers ::receiveWebhook
   */
  public function testResponseForEmptyPayload() {
    $request = Request::createFromGlobals();
    $response = $this->chWebhookController->receiveWebhook($request);
    $this->assertEquals(400, $response->getStatusCode(), 'Webhook status code should be 400');
  }

  /**
   * Tests setWebhookType.
   *
   * @covers ::setWebhookType
   */
  public function testSetWebhookType() {
    /* Validates if uuid is valid webhook-type should be Automatic. */
    $payload = '{"uuid":"f294b86b-8be2-4ac0-bef4-f3696e292ebb","account_id":"KIRTIGARGCH","status":"successful","crud":"update","assets":{"uuid":"3b052b9a-6581-4aa3-acd0-c7bac2d37558","type":"client","url":"/entities/3b052b9a-6581-4aa3-acd0-c7bac2d37558"},"endpoint_id":"","endpoint":"https://kirti-sub1.in.ngrok.io/acquia-contenthub/webhook","initiator":"3b052b9a-6581-4aa3-acd0-c7bac2d37558","publickey":"Webhook","nonce":"c812041c-f47e-4fdc-b635-348dcf5befb6","signature-version":"2.0","realm":"Plexus-webhook","date":"1696590980","requestid":"b2ae9609-ca32-4b56-b20d-e793b319b7a7","api_version":2,"signas":"2.0","reason":"18563987-e1db-4e88-9ecd-a30bf79fccff"}';
    $payload = json_decode($payload, TRUE);
    $new_payload = $this->chWebhookController->setWebhookType($payload);
    $this->assertEquals('Automatic', $new_payload['webhook-type'], 'The result should return Automatic');

    /* Validates if uuid is invalid webhook-type should be Manual. */
    $payload = '{"uuid":"0","account_id":"KIRTIGARGCH","status":"successful","crud":"update","assets":{"uuid":"3b052b9a-6581-4aa3-acd0-c7bac2d37558","type":"client","url":"/entities/3b052b9a-6581-4aa3-acd0-c7bac2d37558"},"endpoint_id":"","endpoint":"https://kirti-sub1.in.ngrok.io/acquia-contenthub/webhook","initiator":"3b052b9a-6581-4aa3-acd0-c7bac2d37558","publickey":"Webhook","nonce":"c812041c-f47e-4fdc-b635-348dcf5befb6","signature-version":"2.0","realm":"Plexus-webhook","date":"1696590980","requestid":"b2ae9609-ca32-4b56-b20d-e793b319b7a7","api_version":2,"signas":"2.0","reason":"18563987-e1db-4e88-9ecd-a30bf79fccff"}';
    $payload = json_decode($payload, TRUE);
    $new_payload = $this->chWebhookController->setWebhookType($payload);
    $this->assertEquals('Manual', $new_payload['webhook-type'], 'The result should return Manual');

    /* Validates if uuid is empty webhook-type should be Manual. */
    $payload = '{"uuid":"","account_id":"KIRTIGARGCH","status":"successful","crud":"update","assets":{"uuid":"3b052b9a-6581-4aa3-acd0-c7bac2d37558","type":"client","url":"/entities/3b052b9a-6581-4aa3-acd0-c7bac2d37558"},"endpoint_id":"","endpoint":"https://kirti-sub1.in.ngrok.io/acquia-contenthub/webhook","initiator":"3b052b9a-6581-4aa3-acd0-c7bac2d37558","publickey":"Webhook","nonce":"c812041c-f47e-4fdc-b635-348dcf5befb6","signature-version":"2.0","realm":"Plexus-webhook","date":"1696590980","requestid":"b2ae9609-ca32-4b56-b20d-e793b319b7a7","api_version":2,"signas":"2.0","reason":"18563987-e1db-4e88-9ecd-a30bf79fccff"}';
    $payload = json_decode($payload, TRUE);
    $new_payload = $this->chWebhookController->setWebhookType($payload);
    $this->assertEquals('Manual', $new_payload['webhook-type'], 'The result should return Manual');
  }

  /**
   * Tests setWebhookReason.
   *
   * @covers ::setWebhookReason
   */
  public function testSetWebhookReason() {
    /* Validates if payload reason is empty it should be changed to Manual. */
    $payload = '{"uuid":"","account_id":"KIRTIGARGCH","status":"successful","crud":"update","assets":{"uuid":"3b052b9a-6581-4aa3-acd0-c7bac2d37558","type":"client","url":"/entities/3b052b9a-6581-4aa3-acd0-c7bac2d37558"},"endpoint_id":"","endpoint":"https://kirti-sub1.in.ngrok.io/acquia-contenthub/webhook","initiator":"3b052b9a-6581-4aa3-acd0-c7bac2d37558","publickey":"Webhook","nonce":"c812041c-f47e-4fdc-b635-348dcf5befb6","signature-version":"2.0","realm":"Plexus-webhook","date":"1696590980","requestid":"b2ae9609-ca32-4b56-b20d-e793b319b7a7","api_version":2,"signas":"2.0"}';
    $payload = json_decode($payload, TRUE);
    $new_payload = $this->chWebhookController->setWebhookReason($payload);
    $this->assertEquals('Manual', $new_payload['reason'], 'The result should return Manual');

    /* Validates if payload reason contains uuid, resulting string should contain string 'Filter Uuid(s)'. */
    $payload = '{"uuid":"0","account_id":"KIRTIGARGCH","status":"successful","crud":"update","assets":{"uuid":"3b052b9a-6581-4aa3-acd0-c7bac2d37558","type":"client","url":"/entities/3b052b9a-6581-4aa3-acd0-c7bac2d37558"},"endpoint_id":"","endpoint":"https://kirti-sub1.in.ngrok.io/acquia-contenthub/webhook","initiator":"3b052b9a-6581-4aa3-acd0-c7bac2d37558","publickey":"Webhook","nonce":"c812041c-f47e-4fdc-b635-348dcf5befb6","signature-version":"2.0","realm":"Plexus-webhook","date":"1696590980","requestid":"b2ae9609-ca32-4b56-b20d-e793b319b7a7","api_version":2,"signas":"2.0","reason":"18563987-e1db-4e88-9ecd-a30bf79fccff"}';
    $payload = json_decode($payload, TRUE);
    $new_payload = $this->chWebhookController->setWebhookReason($payload);
    $this->assertStringContainsString('Filter Uuid(s)', $new_payload['reason'], 'The result should contain Filter Uuid(s)');

    /* Validates if reason is neither empty not contain uuids, same reason should be returned. */
    $payload = '{"uuid":"f294b86b-8be2-4ac0-bef4-f3696e292ebb","account_id":"KIRTIGARGCH","status":"successful","crud":"update","assets":{"uuid":"3b052b9a-6581-4aa3-acd0-c7bac2d37558","type":"client","url":"/entities/3b052b9a-6581-4aa3-acd0-c7bac2d37558"},"endpoint_id":"","endpoint":"https://kirti-sub1.in.ngrok.io/acquia-contenthub/webhook","initiator":"3b052b9a-6581-4aa3-acd0-c7bac2d37558","publickey":"Webhook","nonce":"c812041c-f47e-4fdc-b635-348dcf5befb6","signature-version":"2.0","realm":"Plexus-webhook","date":"1696590980","requestid":"b2ae9609-ca32-4b56-b20d-e793b319b7a7","api_version":2,"signas":"2.0","reason":"Dependency"}';
    $payload = json_decode($payload, TRUE);
    $new_payload = $this->chWebhookController->setWebhookReason($payload);
    $this->assertEquals('Dependency', $new_payload['reason'], 'The result should return Dependency');
  }

  /**
   * Tests beautifyLogMessage.
   *
   * @covers ::beautifyLogMessage
   */
  public function testBeautifyLogMessage() {
    /* Validates if beautified payload starts with [. */
    $payload = '{"uuid":"f294b86b-8be2-4ac0-bef4-f3696e292ebb","account_id":"KIRTIGARGCH","status":"successful","crud":"update","assets":{"uuid":"3b052b9a-6581-4aa3-acd0-c7bac2d37558","type":"client","url":"/entities/3b052b9a-6581-4aa3-acd0-c7bac2d37558"},"endpoint_id":"","endpoint":"https://kirti-sub1.in.ngrok.io/acquia-contenthub/webhook","initiator":"3b052b9a-6581-4aa3-acd0-c7bac2d37558","publickey":"Webhook","nonce":"c812041c-f47e-4fdc-b635-348dcf5befb6","signature-version":"2.0","realm":"Plexus-webhook","date":"1696590980","requestid":"b2ae9609-ca32-4b56-b20d-e793b319b7a7","api_version":2,"signas":"2.0","reason":"Dependency"}';
    $payload = json_decode($payload, TRUE);
    $message = $this->chWebhookController->beautifyLogMessage($payload);
    $this->assertStringStartsWith('[', $message, 'Message should start with [');
  }

}
