<?php

declare(strict_types=1);

namespace Drupal\Tests\acquia_dam\Unit\Service;

use Drupal\acquia_dam\AssetUpdater;
use Drupal\acquia_dam\AssetUpdateChecker;
use Drupal\acquia_dam\AssetVersionResolver;
use Drupal\acquia_dam\Client\AcquiaDamClientFactory;
use Drupal\acquia_dam\IntegrationLinkRegister;
use Drupal\acquia_dam\Service\IntegrationLinksBatchProcessor;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
use Drupal\Core\Queue\QueueFactory;
use Drupal\Core\Queue\QueueWorkerManagerInterface;
use Drupal\Tests\UnitTestCase;

/**
 * Unit tests for IntegrationLinksBatchProcessor service.
 *
 * @group acquia_dam
 * @coversDefaultClass \Drupal\acquia_dam\Service\IntegrationLinksBatchProcessor
 */
class IntegrationLinksBatchProcessorTest extends UnitTestCase {

  /**
   * The integration link register mock.
   *
   * @var \Drupal\acquia_dam\IntegrationLinkRegister|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $integrationLinkRegister;

  /**
   * The entity type manager mock.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $entityTypeManager;

  /**
   * The database mock.
   *
   * @var \Drupal\Core\Database\Connection|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $database;

  /**
   * The module handler mock.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $moduleHandler;

  /**
   * The logger factory mock.
   *
   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $loggerFactory;

  /**
   * The asset updater.
   *
   * @var \Drupal\acquia_dam\AssetUpdater
   */
  protected $assetUpdater;

  /**
   * The batch processor under test.
   *
   * @var \Drupal\acquia_dam\Service\IntegrationLinksBatchProcessor
   */
  protected $batchProcessor;

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();

    $this->integrationLinkRegister = $this->createMock(IntegrationLinkRegister::class);
    $this->entityTypeManager = $this->createMock(EntityTypeManagerInterface::class);
    $this->database = $this->createMock(Connection::class);
    $this->moduleHandler = $this->createMock(ModuleHandlerInterface::class);
    $this->loggerFactory = $this->createMock(LoggerChannelFactoryInterface::class);

    // Create a real AssetUpdater instance with mocked dependencies.
    $assetUpdateChecker = $this->createMock(AssetUpdateChecker::class);
    $assetVersionResolver = $this->createMock(AssetVersionResolver::class);
    $queueFactory = $this->createMock(QueueFactory::class);
    $queueWorkerManager = $this->createMock(QueueWorkerManagerInterface::class);
    $assetUpdaterLogger = $this->createMock(LoggerChannelFactoryInterface::class);
    $client_factory = $this->createMock(AcquiaDamClientFactory::class);
    $time = $this->createMock(TimeInterface::class);

    $this->assetUpdater = new AssetUpdater(
      $this->entityTypeManager,
      $assetUpdateChecker,
      $assetVersionResolver,
      $queueFactory,
      $queueWorkerManager,
      $assetUpdaterLogger,
      $client_factory,
      $time
    );

    // Setup logger.
    $logger = $this->createMock(LoggerChannelInterface::class);
    $this->loggerFactory->method('get')->willReturn($logger);

    $this->batchProcessor = new IntegrationLinksBatchProcessor(
      $this->integrationLinkRegister,
      $this->entityTypeManager,
      $this->database,
      $this->moduleHandler,
      $this->loggerFactory,
      $this->assetUpdater
    );
  }

  /**
   * @covers ::isEnhancedModeEnabled
   */
  public function testIsEnhancedModeEnabledTrue(): void {
    $this->moduleHandler->method('moduleExists')
      ->with('acquia_dam_integration_links')
      ->willReturn(TRUE);

    $result = $this->batchProcessor->isEnhancedModeEnabled();
    $this->assertTrue($result);
  }

  /**
   * @covers ::isEnhancedModeEnabled
   */
  public function testIsEnhancedModeEnabledFalse(): void {
    $this->moduleHandler->method('moduleExists')
      ->with('acquia_dam_integration_links')
      ->willReturn(FALSE);

    $result = $this->batchProcessor->isEnhancedModeEnabled();
    $this->assertFalse($result);
  }

  /**
   * @covers ::processMediaEntities
   */
  public function testProcessMediaEntitiesEmpty(): void {
    // Mock the media_type storage to return no media types with DAM source.
    $storage = $this->createMock(EntityStorageInterface::class);
    $storage->method('loadByProperties')->willReturn([]);

    $this->entityTypeManager->method('getStorage')
      ->willReturnCallback(function ($entity_type) use ($storage) {
        if ($entity_type === 'media_type') {
          return $storage;
        }
        return $this->createMock(EntityStorageInterface::class);
      });

    // Mock destruct method exists.
    $this->integrationLinkRegister->method('destruct');

    $results = $this->batchProcessor->processMediaEntities();

    $this->assertSame(0, $results['total_queued']);
    $this->assertSame(0, $results['total_processed']);
    $this->assertEmpty($results['media_types']);
  }

  /**
   * @covers ::processContentEntities
   */
  public function testProcessContentEntitiesWithEnhancedModeDisabled(): void {
    $this->moduleHandler->method('moduleExists')->willReturn(FALSE);

    // Mock destruct method.
    $this->integrationLinkRegister->method('destruct');

    $results = $this->batchProcessor->processContentEntities();

    $this->assertSame(0, $results['content_queued']);
    $this->assertSame(0, $results['content_processed']);
  }

}
