<?php

declare(strict_types=1);

namespace Drupal\Tests\flowdrop_interrupt\Unit\DTO;

use Drupal\flowdrop_interrupt\DTO\InterruptCreationData;
use Drupal\flowdrop_interrupt\Enum\InterruptDirection;
use Drupal\flowdrop_interrupt\Enum\InterruptType;
use Drupal\Tests\UnitTestCase;

/**
 * Tests the InterruptCreationData value object.
 *
 * @coversDefaultClass \Drupal\flowdrop_interrupt\DTO\InterruptCreationData
 * @group flowdrop_interrupt
 */
class InterruptCreationDataTest extends UnitTestCase {

  /**
   * Minimal construction (the four required fields only).
   */
  public function testMinimalConstruction(): void {
    $data = new InterruptCreationData(
      type: InterruptType::SchemaForm,
      workflowId: 'wf',
      nodeId: 'node-1',
      message: 'hello',
    );
    $this->assertSame(InterruptType::SchemaForm, $data->type);
    $this->assertSame('wf', $data->workflowId);
    $this->assertSame('node-1', $data->nodeId);
    $this->assertSame('hello', $data->message);
    $this->assertSame([], $data->schema);
    $this->assertSame([], $data->options);
    $this->assertSame([], $data->context);
    $this->assertNull($data->defaultValue);
    $this->assertNull($data->pipelineId);
    $this->assertNull($data->sessionId);
    $this->assertNull($data->expiresIn);
    $this->assertNull($data->assignedToUid);
    $this->assertNull($data->direction);
    $this->assertNull($data->jobId);
    $this->assertNull($data->linkedInterruptId);
  }

  /**
   * Fully-populated construction round-trips all named arguments.
   */
  public function testFullyPopulated(): void {
    $data = new InterruptCreationData(
      type: InterruptType::WorkflowExecution,
      workflowId: 'wf',
      nodeId: 'n',
      message: 'm',
      schema: ['type' => 'object'],
      options: [['value' => 'a', 'label' => 'A']],
      context: ['k' => 'v'],
      defaultValue: 'preset',
      pipelineId: 'pipe-1',
      sessionId: 99,
      expiresIn: 60,
      assignedToUid: 42,
      direction: InterruptDirection::Inward,
      jobId: 7,
      linkedInterruptId: 'linked-uuid',
    );
    $this->assertSame('wf', $data->workflowId);
    $this->assertSame(['type' => 'object'], $data->schema);
    $this->assertSame([['value' => 'a', 'label' => 'A']], $data->options);
    $this->assertSame(['k' => 'v'], $data->context);
    $this->assertSame('preset', $data->defaultValue);
    $this->assertSame('pipe-1', $data->pipelineId);
    $this->assertSame(99, $data->sessionId);
    $this->assertSame(60, $data->expiresIn);
    $this->assertSame(42, $data->assignedToUid);
    $this->assertSame(InterruptDirection::Inward, $data->direction);
    $this->assertSame(7, $data->jobId);
    $this->assertSame('linked-uuid', $data->linkedInterruptId);
  }

  /**
   * The DTO is immutable — readonly properties cannot be reassigned.
   */
  public function testIsImmutable(): void {
    $data = new InterruptCreationData(
      type: InterruptType::SchemaForm,
      workflowId: 'wf',
      nodeId: 'n',
      message: 'm',
    );
    $this->expectException(\Error::class);
    // @phpstan-ignore-next-line — deliberately writing to readonly.
    $data->message = 'mutated';
  }

}
