<?php

namespace Drupal\Tests\acquia_contenthub\Unit\Libs\ServiceQueue;

use Drupal\acquia_contenthub\Libs\ServiceQueue\QueueItem;
use Drupal\acquia_contenthub\Libs\ServiceQueue\ServiceQueueEntityActions;
use Drupal\Tests\UnitTestCase;

/**
 * Tests the QueueItem class.
 *
 * @coversDefaultClass \Drupal\acquia_contenthub\Libs\ServiceQueue\QueueItem
 *
 * @group acquia_contenthub
 *
 * @package Drupal\Tests\acquia_contenthub\Unit\Libs\ServiceQueue
 */
class QueueItemTest extends UnitTestCase {

  /**
   * Test creating a QueueItem from an array.
   *
   * @covers ::fromArray
   */
  public function testFromArray(): void {
    $queue_item_data = [
      'id' => '123',
      'entity_uuid' => '5f71af85-cbb0-48ac-84f3-97083bf16367',
      'client_uuid' => '8fb4c61c-bc0c-4451-a1aa-f576bf4eb966',
      'state' => 'queued',
      'payload' => [
        'action' => 'entity_create',
        'reason' => 'interest list',
      ],
      'visible_at' => '1753879023',
      'created_at' => '1753879023',
      'updated_at' => '1753879023',
    ];

    $queue_item = QueueItem::fromArray($queue_item_data);

    $this->assertEquals('123', $queue_item->getId());
    $this->assertEquals('5f71af85-cbb0-48ac-84f3-97083bf16367', $queue_item->getEntityUuid());
    $this->assertEquals('8fb4c61c-bc0c-4451-a1aa-f576bf4eb966', $queue_item->getOwnerUuid());
    $this->assertEquals('queued', $queue_item->getState());
    $this->assertEquals('entity_create', $queue_item->getAction());
    $this->assertEquals('interest list', $queue_item->getReason());
    $this->assertEquals('1753879023', $queue_item->getVisibleAt());
    $this->assertEquals('1753879023', $queue_item->getCreatedAt());
    $this->assertEquals('1753879023', $queue_item->getUpdatedAt());
  }

  /**
   * Test creating a QueueItem with minimal data.
   *
   * @covers ::fromArray
   */
  public function testFromArrayMinimal(): void {
    $queue_item_data = [
      'id' => '123',
      'entity_uuid' => '5f71af85-cbb0-48ac-84f3-97083bf16367',
      'client_uuid' => '8fb4c61c-bc0c-4451-a1aa-f576bf4eb966',
      'state' => 'queued',
    ];

    $queue_item = QueueItem::fromArray($queue_item_data);

    $this->assertEquals('123', $queue_item->getId());
    $this->assertEquals('5f71af85-cbb0-48ac-84f3-97083bf16367', $queue_item->getEntityUuid());
    $this->assertEquals('8fb4c61c-bc0c-4451-a1aa-f576bf4eb966', $queue_item->getOwnerUuid());
    $this->assertEquals('queued', $queue_item->getState());
    $this->assertEquals([], $queue_item->getPayload());
    $this->assertEquals('unknown', $queue_item->getAction());
    $this->assertEmpty($queue_item->getReason());
    $this->assertEquals('', $queue_item->getVisibleAt());
    $this->assertEquals('', $queue_item->getCreatedAt());
    $this->assertEquals('', $queue_item->getUpdatedAt());
  }

  /**
   * Test isActionOneOf method.
   *
   * @covers ::isActionOneOf
   * @covers ::getAction
   */
  public function testIsActionOneOf(): void {
    $queue_item_data = [
      'id' => '123',
      'entity_uuid' => '5f71af85-cbb0-48ac-84f3-97083bf16367',
      'client_uuid' => '8fb4c61c-bc0c-4451-a1aa-f576bf4eb966',
      'state' => 'queued',
      'payload' => [
        'action' => 'entity_create',
      ],
    ];

    $queue_item = QueueItem::fromArray($queue_item_data);

    $this->assertTrue($queue_item->isActionOneOf([
      ServiceQueueEntityActions::CREATE,
      ServiceQueueEntityActions::UPDATE,
    ]));

    $this->assertFalse($queue_item->isActionOneOf([
      ServiceQueueEntityActions::DELETE,
    ]));

    $this->assertFalse($queue_item->isActionOneOf(['nonexistent_action']));
  }

  /**
   * Test isAction method.
   *
   * @covers ::isAction
   */
  public function testIsAction(): void {
    $queue_item_data = [
      'id' => '123',
      'entity_uuid' => '5f71af85-cbb0-48ac-84f3-97083bf16367',
      'client_uuid' => '8fb4c61c-bc0c-4451-a1aa-f576bf4eb966',
      'state' => 'queued',
      'payload' => [
        'action' => 'entity_delete',
      ],
    ];

    $queue_item = QueueItem::fromArray($queue_item_data);

    $this->assertTrue($queue_item->isAction(ServiceQueueEntityActions::DELETE));
    $this->assertFalse($queue_item->isAction(ServiceQueueEntityActions::CREATE));
    $this->assertFalse($queue_item->isAction('nonexistent_action'));
  }

  /**
   * Test toArray method.
   *
   * @covers ::toArray
   */
  public function testToArray(): void {
    $queue_item_data = [
      'id' => '123',
      'entity_uuid' => '5f71af85-cbb0-48ac-84f3-97083bf16367',
      'client_uuid' => '8fb4c61c-bc0c-4451-a1aa-f576bf4eb966',
      'state' => 'queued',
      'payload' => [
        'action' => 'entity_create',
        'reason' => 'interest list',
      ],
      'visible_at' => '1753879023',
      'created_at' => '1753879023',
      'updated_at' => '1753879023',
    ];

    $queue_item = QueueItem::fromArray($queue_item_data);
    $result = $queue_item->toArray();

    $this->assertEquals($queue_item_data, $result);
  }

  /**
   * Test isActionOneOf with no action in payload.
   *
   * @covers ::isActionOneOf
   */
  public function testIsActionOneOfWithNoAction(): void {
    $queue_item_data = [
      'id' => '123',
      'entity_uuid' => '5f71af85-cbb0-48ac-84f3-97083bf16367',
      'client_uuid' => '8fb4c61c-bc0c-4451-a1aa-f576bf4eb966',
      'state' => 'queued',
      'payload' => [],
    ];

    $queue_item = QueueItem::fromArray($queue_item_data);

    $this->assertFalse($queue_item->isActionOneOf([
      ServiceQueueEntityActions::CREATE,
      ServiceQueueEntityActions::UPDATE,
      ServiceQueueEntityActions::DELETE,
    ]));
  }

  /**
   * Test isAction with no action in payload.
   *
   * @covers ::isAction
   */
  public function testIsActionWithNoAction(): void {
    $queue_item_data = [
      'id' => '123',
      'entity_uuid' => '5f71af85-cbb0-48ac-84f3-97083bf16367',
      'client_uuid' => '8fb4c61c-bc0c-4451-a1aa-f576bf4eb966',
      'state' => 'queued',
      'payload' => [],
    ];

    $queue_item = QueueItem::fromArray($queue_item_data);

    $this->assertFalse($queue_item->isAction(ServiceQueueEntityActions::CREATE));
    $this->assertFalse($queue_item->isAction(ServiceQueueEntityActions::DELETE));
  }

  /**
   * Test fromArray validation for required fields.
   *
   * @covers ::fromArray
   */
  public function testFromArrayValidationMissingId(): void {
    $queue_item_data = [
      'entity_uuid' => '5f71af85-cbb0-48ac-84f3-97083bf16367',
      'client_uuid' => '8fb4c61c-bc0c-4451-a1aa-f576bf4eb966',
      'state' => 'queued',
    ];

    $this->expectException(\InvalidArgumentException::class);
    $this->expectExceptionMessage('Required field "id" is missing or empty in queue item data.');
    QueueItem::fromArray($queue_item_data);
  }

  /**
   * Test __toString method.
   *
   * @covers ::__toString
   * @covers ::toArray
   */
  public function testToString(): void {
    $queue_item_data = [
      'id' => '123',
      'entity_uuid' => '5f71af85-cbb0-48ac-84f3-97083bf16367',
      'client_uuid' => '8fb4c61c-bc0c-4451-a1aa-f576bf4eb966',
      'state' => 'queued',
      'payload' => [
        'action' => 'entity_create',
        'reason' => 'interest list',
      ],
      'visible_at' => '1753879023',
      'created_at' => '1753879023',
      'updated_at' => '1753879023',
    ];

    $queue_item = QueueItem::fromArray($queue_item_data);
    $result = (string) $queue_item;

    $decoded = json_decode($result, TRUE);
    $this->assertEquals($queue_item_data, $decoded);
    $this->assertJson($result);
  }

  /**
   * Test getInitiator method.
   *
   * @covers ::getInitiator
   */
  public function testGetInitiator(): void {
    $queue_item_data = [
      'id' => '123',
      'entity_uuid' => '5f71af85-cbb0-48ac-84f3-97083bf16367',
      'client_uuid' => '8fb4c61c-bc0c-4451-a1aa-f576bf4eb966',
      'state' => 'queued',
      'payload' => [
        'initiator' => 'publisher-uuid-123',
        'action' => 'entity_create',
      ],
    ];

    $queue_item = QueueItem::fromArray($queue_item_data);
    $this->assertEquals('publisher-uuid-123', $queue_item->getInitiator());
  }

  /**
   * Test getInitiator method with no initiator in payload.
   *
   * @covers ::getInitiator
   */
  public function testGetInitiatorWithNoInitiator(): void {
    $queue_item_data = [
      'id' => '123',
      'entity_uuid' => '5f71af85-cbb0-48ac-84f3-97083bf16367',
      'client_uuid' => '8fb4c61c-bc0c-4451-a1aa-f576bf4eb966',
      'state' => 'queued',
      'payload' => [
        'action' => 'entity_create',
      ],
    ];

    $queue_item = QueueItem::fromArray($queue_item_data);
    $this->assertEquals('', $queue_item->getInitiator());
  }

  /**
   * Test getReason method.
   *
   * @covers ::getReason
   */
  public function testGetReason(): void {
    $queue_item_data = [
      'id' => '123',
      'entity_uuid' => '5f71af85-cbb0-48ac-84f3-97083bf16367',
      'client_uuid' => '8fb4c61c-bc0c-4451-a1aa-f576bf4eb966',
      'state' => 'queued',
      'payload' => [
        'reason' => 'webhook triggered',
        'action' => 'entity_update',
      ],
    ];

    $queue_item = QueueItem::fromArray($queue_item_data);
    $this->assertEquals('webhook triggered', $queue_item->getReason());
  }

  /**
   * Test getReason method with no reason in payload.
   *
   * @covers ::getReason
   */
  public function testGetReasonWithNoReason(): void {
    $queue_item_data = [
      'id' => '123',
      'entity_uuid' => '5f71af85-cbb0-48ac-84f3-97083bf16367',
      'client_uuid' => '8fb4c61c-bc0c-4451-a1aa-f576bf4eb966',
      'state' => 'queued',
      'payload' => [
        'action' => 'entity_delete',
      ],
    ];

    $queue_item = QueueItem::fromArray($queue_item_data);
    $this->assertEquals('', $queue_item->getReason());
  }

}
