<?php

declare(strict_types=1);

namespace Drupal\Tests\flowdrop\Unit\Utility;

use Drupal\flowdrop\Constants\ReservedName;
use Drupal\flowdrop\Utility\PortExposure;
use Drupal\Tests\UnitTestCase;

/**
 * Tests the single port-exposure accessor the engine reads through.
 *
 * @coversDefaultClass \Drupal\flowdrop\Utility\PortExposure
 * @group flowdrop
 */
class PortExposureTest extends UnitTestCase {

  /**
   * With no config.ports, the metadata default decides.
   *
   * @covers ::isExposed
   */
  public function testFallsBackToMetadataDefault(): void {
    $this->assertTrue(PortExposure::isExposed([], ReservedName::PORT_INPUT, 'value', TRUE));
    $this->assertFalse(PortExposure::isExposed([], ReservedName::PORT_OUTPUT, 'error', FALSE));
  }

  /**
   * An instance entry's explicit `exposed` flag overrides the default.
   *
   * @covers ::isExposed
   */
  public function testInstanceOverrideWins(): void {
    $ports = [
      'inputs' => [['id' => 'value', 'exposed' => FALSE]],
      'outputs' => [['id' => 'error', 'exposed' => TRUE]],
    ];

    // Default-exposed input flipped off.
    $this->assertFalse(PortExposure::isExposed($ports, ReservedName::PORT_INPUT, 'value', TRUE));
    // Default-not-exposed output flipped on.
    $this->assertTrue(PortExposure::isExposed($ports, ReservedName::PORT_OUTPUT, 'error', FALSE));
  }

  /**
   * An entry without an `exposed` key leaves the metadata default in force.
   *
   * @covers ::isExposed
   */
  public function testEntryWithoutFlagUsesDefault(): void {
    $ports = ['inputs' => [['id' => 'value']]];

    $this->assertTrue(PortExposure::isExposed($ports, ReservedName::PORT_INPUT, 'value', TRUE));
    $this->assertFalse(PortExposure::isExposed($ports, ReservedName::PORT_INPUT, 'value', FALSE));
  }

  /**
   * A port absent from the list falls back to its default; direction matters.
   *
   * @covers ::isExposed
   */
  public function testAbsentPortAndDirectionScoping(): void {
    $ports = ['inputs' => [['id' => 'other', 'exposed' => FALSE]]];

    // 'value' is not listed -> default.
    $this->assertTrue(PortExposure::isExposed($ports, ReservedName::PORT_INPUT, 'value', TRUE));
    // The inputs entry must not leak into the outputs direction.
    $this->assertTrue(PortExposure::isExposed($ports, ReservedName::PORT_OUTPUT, 'other', TRUE));
  }

}
