<?php

declare(strict_types=1);

namespace Drupal\Tests\flowdrop_orchestration\Unit\DTO;

use Drupal\Tests\UnitTestCase;
use Drupal\flowdrop_orchestration\DTO\Orchestrator\OrchestrationRequest;

/**
 * Tests the OrchestrationRequest DTO.
 *
 * @coversDefaultClass \Drupal\flowdrop_orchestration\DTO\Orchestrator\OrchestrationRequest
 * @group flowdrop_orchestration
 */
class OrchestrationRequestTest extends UnitTestCase {

  /**
   * @covers ::__construct
   * @covers ::getWorkflowId
   * @covers ::getWorkflow
   * @covers ::getInitialData
   * @covers ::getOptions
   */
  public function testConstructorAndGetters(): void {
    $request = new OrchestrationRequest(
      workflowId: "wf_1",
      pipelineId: "pl_1",
      workflow: ["nodes" => [], "edges" => []],
      initialData: ["key" => "val"],
      options: ["orchestrator" => "sync"],
    );

    $this->assertEquals("wf_1", $request->getWorkflowId());
    $this->assertEquals("pl_1", $request->getPipelineId());
    $this->assertEquals(["nodes" => [], "edges" => []], $request->getWorkflow());
    $this->assertEquals(["key" => "val"], $request->getInitialData());
    $this->assertEquals("sync", $request->getOption("orchestrator"));
    $this->assertNull($request->getOption("missing"));
    $this->assertEquals("default", $request->getOption("missing", "default"));
  }

  /**
   * @covers ::create
   */
  public function testCreate(): void {
    $request = OrchestrationRequest::create(
      "wf_2",
      ["nodes" => []],
      ["data" => TRUE],
      ["opt" => "val"],
    );
    $this->assertEquals("wf_2", $request->getWorkflowId());
    $this->assertStringStartsWith("pipeline_wf_2_", $request->getPipelineId());
  }

  /**
   * @covers ::hasPreloadedState
   */
  public function testHasPreloadedStateFalse(): void {
    $request = OrchestrationRequest::create("wf", []);
    $this->assertFalse($request->hasPreloadedState());
    $this->assertNull($request->getInitialSnapshot());
    $this->assertEquals([], $request->getPreloadedNodeOutputs());
    $this->assertEquals([], $request->getPreloadedCompletedNodeIds());
  }

  /**
   * @covers ::withOptions
   */
  public function testWithOptions(): void {
    $request = OrchestrationRequest::create("wf", [], [], ["a" => 1]);
    $new = $request->withOptions(["b" => 2]);
    $this->assertNotSame($request, $new);
    $this->assertNull($request->getOption("b"));
    $this->assertEquals(1, $new->getOption("a"));
    $this->assertEquals(2, $new->getOption("b"));
  }

  /**
   * @covers ::toArray
   * @covers ::fromArray
   */
  public function testRoundTrip(): void {
    $request = OrchestrationRequest::create("wf_rt", ["nodes" => []], ["data" => TRUE]);
    $restored = OrchestrationRequest::fromArray($request->toArray());
    $this->assertEquals($request->getWorkflowId(), $restored->getWorkflowId());
    $this->assertEquals($request->getInitialData(), $restored->getInitialData());
  }

}
