<?php

declare(strict_types=1);

namespace Drupal\Tests\flowdrop_interrupt\Unit\Handler;

use Drupal\flowdrop_interrupt\DTO\ExecutionStamp;
use Drupal\flowdrop_interrupt\DTO\InterruptCreationData;
use Drupal\flowdrop_interrupt\Entity\FlowDropInterruptInterface;
use Drupal\flowdrop_interrupt\Enum\InterruptDirection;
use Drupal\flowdrop_interrupt\Enum\InterruptType;
use Drupal\flowdrop_interrupt\Handler\InwardSignalMessageHandler;
use Drupal\flowdrop_interrupt\Message\InwardSignalMessage;
use Drupal\flowdrop_interrupt\Service\InterruptFactoryInterface;
use Drupal\Tests\UnitTestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;

/**
 * @coversDefaultClass \Drupal\flowdrop_interrupt\Handler\InwardSignalMessageHandler
 * @group flowdrop_interrupt
 */
class InwardSignalMessageHandlerTest extends UnitTestCase {

  use ProphecyTrait;

  /**
   * Tests that supports() returns the message class name.
   */
  public function testSupportsReturnsMessageClass(): void {
    $this->assertSame(InwardSignalMessage::class, InwardSignalMessageHandler::supports());
  }

  /**
   * Tests that handle projects signal fields onto creation data.
   */
  public function testHandleProjectsSignalFieldsOntoCreationData(): void {
    $entity = $this->prophesize(FlowDropInterruptInterface::class)->reveal();
    $factory = $this->prophesize(InterruptFactoryInterface::class);
    $factory->create(Argument::that(function (InterruptCreationData $data) {
      return $data->type === InterruptType::Cancel
        && $data->workflowId === 'wf'
        && $data->nodeId === 'signal:cancel'
        && $data->message === 'cancel by operator'
        && $data->assignedToUid === 42
        && $data->direction === InterruptDirection::Inward
        && $data->targetPipelineId === 'pipe-target'
        && $data->initiatorUid === 42
        && $data->reason === 'operator cancelled';
    }))->shouldBeCalled()->willReturn($entity);

    $handler = new InwardSignalMessageHandler($factory->reveal());
    $result = $handler->handle(
      new InwardSignalMessage(
        type: InterruptType::Cancel,
        message: 'cancel by operator',
        targetPipelineId: 'pipe-target',
        initiatorUid: 42,
        reason: 'operator cancelled',
      ),
      new ExecutionStamp(workflowId: 'wf', nodeId: 'signal:cancel'),
    );

    $this->assertSame($entity, $result);
  }

}
