<?php

namespace Drupal\Tests\acquia_contenthub\Unit\Libs\PullSyndication;

use Drupal\acquia_contenthub\Exception\QueueItemInputViolationException;
use Drupal\acquia_contenthub\Libs\PullSyndication\QueueItemInputValidator;
use Drupal\Tests\UnitTestCase;

/**
 * Tests the QueueItemInputValidator class.
 *
 * @coversDefaultClass \Drupal\acquia_contenthub\Libs\PullSyndication\QueueItemInputValidator
 *
 * @group acquia_contenthub
 *
 * @package Drupal\Tests\acquia_contenthub\Unit\Libs\PullSyndication
 */
class QueueItemInputValidatorTest extends UnitTestCase {

  /**
   * Tests validateVisibilityTimeout with valid timeout values.
   *
   * @covers ::validateVisibilityTimeout
   */
  public function testValidateVisibilityTimeoutValid(): void {
    // Cover all valid units and include boundary values (maximum) and zero.
    $valid_values = [
      '1ns',
      '1us',
      '900µs',
      '898776ms',
      '0s',
      '0ms',
      '0us',
      '0µs',
      '0ns',
      '0m',
      '0h',
      '60s',
      '123233s',
      '3322m',
      '226h',
      '336h',
      '1209600s',
      '20160m',
      '1209600000ms',
      '1209600000000us',
      '1209600000000µs',
      '1209600000000000ns',
    ];

    foreach ($valid_values as $value) {
      try {
        QueueItemInputValidator::validateVisibilityTimeout($value);
        // Count the successful validation as an assertion to make intent
        // explicit.
        $this->addToAssertionCount(1);
      }
      catch (QueueItemInputViolationException $e) {
        $this->fail("Expected value '$value' to be valid but got exception: {$e->getMessage()}");
      }
    }
  }

  /**
   * Tests validateVisibilityTimeout with invalid format values.
   *
   * @covers ::validateVisibilityTimeout
   */
  public function testValidateVisibilityTimeoutInvalidFormat(): void {
    // Test empty string.
    $this->expectException(QueueItemInputViolationException::class);
    $this->expectExceptionMessage('Invalid visibility timeout format. Must be suffixed with duration unit. E.g. 3600s, 60m, 1h. Valid units : ns, us, µs, ms, s, m, h');
    QueueItemInputValidator::validateVisibilityTimeout('');

    $this->expectException(QueueItemInputViolationException::class);
    $this->expectExceptionMessage('Invalid visibility timeout format. Must be suffixed with duration unit. E.g. 3600s, 60m, 1h. Valid units : ns, us, µs, ms, s, m, h');
    QueueItemInputValidator::validateVisibilityTimeout('12');
  }

  /**
   * Tests validateVisibilityTimeout with timeout exceeding maximum.
   *
   * @covers ::validateVisibilityTimeout
   */
  public function testValidateVisibilityTimeoutExceedsMaximum(): void {
    $this->expectException(QueueItemInputViolationException::class);
    $this->expectExceptionMessage('Visibility timeout cannot exceed 336h.');
    QueueItemInputValidator::validateVisibilityTimeout('337h');
  }

  /**
   * Tests isWithinSyndicationLimit with valid limit values.
   *
   * @covers ::isWithinSyndicationLimit
   */
  public function testIsWithinSyndicationLimitValid(): void {
    // Test minimum valid value.
    $result = QueueItemInputValidator::isWithinSyndicationLimit(1);
    $this->assertTrue($result, 'Expected TRUE for minimum limit value.');

    // Test maximum valid value.
    $result = QueueItemInputValidator::isWithinSyndicationLimit(100);
    $this->assertTrue($result, 'Expected TRUE for maximum limit value.');

    $result = QueueItemInputValidator::isWithinSyndicationLimit(75);
    $this->assertTrue($result, 'Expected TRUE for valid limit value.');
  }

  /**
   * Tests isWithinSyndicationLimit with invalid limit values.
   *
   * @covers ::isWithinSyndicationLimit
   */
  public function testIsWithinSyndicationLimitInvalid(): void {
    // Test value below minimum.
    $result = QueueItemInputValidator::isWithinSyndicationLimit(0);
    $this->assertFalse($result, 'Expected FALSE for limit below minimum.');

    $result = QueueItemInputValidator::isWithinSyndicationLimit(-1);
    $this->assertFalse($result, 'Expected FALSE for negative limit.');

    $result = QueueItemInputValidator::isWithinSyndicationLimit(-10);
    $this->assertFalse($result, 'Expected FALSE for negative limit.');

    // Test value above maximum.
    $result = QueueItemInputValidator::isWithinSyndicationLimit(101);
    $this->assertFalse($result, 'Expected FALSE for limit above maximum.');

    $result = QueueItemInputValidator::isWithinSyndicationLimit(200);
    $this->assertFalse($result, 'Expected FALSE for limit above maximum.');

  }

}
