<?php

declare(strict_types=1);

namespace Drupal\Tests\flowdrop\Unit\DTO\NodeMetadata;

use Drupal\Tests\UnitTestCase;
use Drupal\flowdrop\DTO\NodeMetadata\NodePort;

/**
 * Tests the NodePort DTO.
 *
 * @coversDefaultClass \Drupal\flowdrop\DTO\NodeMetadata\NodePort
 * @group flowdrop
 */
class NodePortTest extends UnitTestCase {

  /**
   * @covers ::input
   * @covers ::isInput
   * @covers ::isOutput
   */
  public function testInputFactory(): void {
    $port = NodePort::input("data_in", "Data In", "json", TRUE, "Required data input");
    $this->assertEquals("data_in", $port->id);
    $this->assertEquals("Data In", $port->name);
    $this->assertEquals(NodePort::TYPE_INPUT, $port->type);
    $this->assertEquals("json", $port->dataType);
    $this->assertTrue($port->required);
    $this->assertTrue($port->isInput());
    $this->assertFalse($port->isOutput());
  }

  /**
   * @covers ::output
   * @covers ::isOutput
   */
  public function testOutputFactory(): void {
    $port = NodePort::output("result", "Result", "string", "Output result");
    $this->assertEquals(NodePort::TYPE_OUTPUT, $port->type);
    $this->assertFalse($port->required);
    $this->assertTrue($port->isOutput());
    $this->assertFalse($port->isInput());
  }

  /**
   * @covers ::hasDefaultValue
   */
  public function testHasDefaultValue(): void {
    $withDefault = NodePort::input("in", "In", "string", FALSE, "", "default_val");
    $withoutDefault = NodePort::input("in", "In", "string");
    $this->assertTrue($withDefault->hasDefaultValue());
    $this->assertFalse($withoutDefault->hasDefaultValue());
  }

  /**
   * @covers ::fromArray
   * @covers ::toArray
   */
  public function testRoundTrip(): void {
    $port = NodePort::input("test_port", "Test Port", "number", TRUE, "A test port", 42);
    $restored = NodePort::fromArray($port->toArray());
    $this->assertEquals($port->toArray(), $restored->toArray());
  }

  /**
   * @covers ::fromArray
   */
  public function testFromArrayDefaults(): void {
    $port = NodePort::fromArray(["id" => "minimal"]);
    $this->assertEquals("minimal", $port->id);
    $this->assertEquals("minimal", $port->name);
    $this->assertEquals(NodePort::TYPE_INPUT, $port->type);
    $this->assertEquals("string", $port->dataType);
    $this->assertFalse($port->required);
  }

  /**
   * Tests constant values are stable.
   */
  public function testTypeConstants(): void {
    $this->assertEquals("input", NodePort::TYPE_INPUT);
    $this->assertEquals("output", NodePort::TYPE_OUTPUT);
  }

}
