<?php

declare(strict_types=1);

namespace Drupal\Tests\flowdrop_runtime\Unit\Event;

use Drupal\flowdrop_runtime\Event\PipelineSignalPollEvent;
use Drupal\Tests\UnitTestCase;

/**
 * Tests PipelineSignalPollEvent's attach-once semantics.
 *
 * @coversDefaultClass \Drupal\flowdrop_runtime\Event\PipelineSignalPollEvent
 * @group flowdrop_runtime
 */
class PipelineSignalPollEventTest extends UnitTestCase {

  /**
   * Default state: no signal attached.
   */
  public function testDefaultState(): void {
    $event = new PipelineSignalPollEvent('p1', 'e1', 'w1');
    $this->assertNull($event->getSignal());
    $this->assertSame('p1', $event->pipelineId);
    $this->assertSame('e1', $event->executionId);
    $this->assertSame('w1', $event->workflowId);
  }

  /**
   * The attachCancel method populates the signal with the cancel action.
   */
  public function testAttachCancel(): void {
    $event = new PipelineSignalPollEvent('p1', 'e1', 'w1');
    $event->attachCancel('uuid-1', 'stop now', 42);
    $signal = $event->getSignal();
    $this->assertSame(PipelineSignalPollEvent::ACTION_CANCEL, $signal['action']);
    $this->assertSame('uuid-1', $signal['signal_id']);
    $this->assertSame('stop now', $signal['reason']);
    $this->assertSame(42, $signal['initiator_uid']);
  }

  /**
   * The attachPause method populates the signal with the pause action.
   */
  public function testAttachPause(): void {
    $event = new PipelineSignalPollEvent('p1', 'e1', 'w1');
    $event->attachPause('uuid-2', NULL, NULL);
    $signal = $event->getSignal();
    $this->assertSame(PipelineSignalPollEvent::ACTION_PAUSE, $signal['action']);
    $this->assertSame('uuid-2', $signal['signal_id']);
    $this->assertNull($signal['reason']);
    $this->assertNull($signal['initiator_uid']);
  }

  /**
   * Subsequent attach calls throw — only one subscriber may attach.
   */
  public function testDoubleAttachThrows(): void {
    $event = new PipelineSignalPollEvent('p1', 'e1', 'w1');
    $event->attachCancel('uuid-1', NULL, NULL);

    $this->expectException(\LogicException::class);
    $this->expectExceptionMessageMatches('/already attached/');
    $event->attachPause('uuid-2', NULL, NULL);
  }

}
