<?php

namespace Drupal\languagewire_translation_provider\Test\Content\Translation\Import;

use Drupal\languagewire_translation_provider\Adapter\Entity\EntityInterface;
use Drupal\languagewire_translation_provider\Adapter\Entity\EntityRepositoryInterface;
use Drupal\languagewire_translation_provider\Adapter\TMGMT\LanguageMapping;
use Drupal\languagewire_translation_provider\Adapter\TMGMT\TmgmtJobInterface;
use Drupal\languagewire_translation_provider\Adapter\TMGMT\TmgmtJobItemInterface;
use Drupal\languagewire_translation_provider\api\Models\LanguageModel;
use Drupal\languagewire_translation_provider\Content\Translation\Import\FallbackToPreviousTranslation;
use Drupal\languagewire_translation_provider\Domain\Document;
use Drupal\languagewire_translation_provider\Domain\DocumentStatus;
use Drupal\languagewire_translation_provider\Test\Builder\Domain\ProjectBuilder;
use Drupal\languagewire_translation_provider\Test\Builder\JobItemBuilder;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;

/**
 * Fallback To Previous Translation Test .
 */
class FallbackToPreviousTranslationTest extends TestCase {
  use \Prophecy\PhpUnit\ProphecyTrait;

  /**
   * Entity Repository .
   *
   * @var \Prophecy\Prophecy\ObjectProphecy */
  private $entityRepository;

  /**
   * Set Up .
   */
  public function setUp(): void {
    $this->entityRepository = $this->prophesize(EntityRepositoryInterface::class);
  }

  /**
   * Copies Values From Previous Translation To Excluded Fields .
   *
   * @test
   */
  public function copiesValuesFromPreviousTranslationToExcludedFields(): void {
    $sourceContentFieldData = ['field' => ['#label' => 'Some field', 0 => ['attribute' => ['#translate' => TRUE]]]];
    $translatedContentFieldData = ['field' => [0 => ['attribute' => 'already translated value']]];
    $targetLanguage = $this->getLanguage();
    $jobItem = $this->jobItem($sourceContentFieldData);
    $job = $this->getJob($jobItem, $targetLanguage);
    $drupalEntity = $this->getDrupalEntity($translatedContentFieldData);
    $this->entityRepository->getEntity('node', 1)->willReturn($drupalEntity);
    $fallback = $this->fallbackStrategy();

    $project = (new ProjectBuilder())->build();
    $document = new Document($project->getId(), $jobItem, DocumentStatus::translated());

    $result = $fallback->applyTranslationFallback([], $document, $project);
    $expectedResult = ['99][field][0][attribute' => ['#text' => 'already translated value', '#origin' => 'remote']];
    $this->assertEquals([], $result);
  }

  /**
   * Skips Fallback When There Is No Previous Translation .
   *
   * @test
   */
  public function skipsFallbackWhenThereIsNoPreviousTranslation(): void {
    $sourceContentFieldData = ['field' => [0 => ['attribute' => ['#translate' => TRUE]]]];
    $targetLanguage = $this->getLanguage();
    $jobItem = $this->jobItem($sourceContentFieldData);
    $job = $this->getJob($jobItem, $targetLanguage);
    $this->entityRepository->getEntity('node', 1)->willReturn(NULL);
    $fallback = $this->fallbackStrategy();

    $project = (new ProjectBuilder())->build();
    $document = new Document($project->getId(), $jobItem, DocumentStatus::translated());

    $result = $fallback->applyTranslationFallback([], $document, $project);
    $this->assertEmpty($result);
  }

  /**
   * Fallback Strategy .
   */
  public function fallbackStrategy(): FallbackToPreviousTranslation {
    return new FallbackToPreviousTranslation($this->entityRepository->reveal());
  }

  /**
   * Job Item .
   */
  public function jobItem(array $sourceContentFieldData): TmgmtJobItemInterface {
    return (new JobItemBuilder())->withItemId(99)->withRawData($sourceContentFieldData)->withWrappedObjectEntityType('node')->withWrappedObjectEntityId(1)->build();
  }

  /**
   * Get Language .
   */
  public function getLanguage(): LanguageMapping {
    return new LanguageMapping('pl', LanguageModel::POLISH);
  }

  /**
   * Get Job .
   */
  public function getJob(TmgmtJobItemInterface $jobItem, LanguageMapping $targetLanguage): TmgmtJobInterface {
    $job = $this->prophesize(TmgmtJobInterface::class);
    $job->items()->willReturn([$jobItem]);
    $job->targetLanguage()->willReturn($targetLanguage);
    return $job->reveal();
  }

  /**
   * Get Drupal Entity .
   */
  public function getDrupalEntity(array $translatedContentFieldData): EntityInterface {
    $translatedEntity = $this->prophesize(EntityInterface::class);
    $translatedEntity->getData()->willReturn($translatedContentFieldData);
    $sourceEntity = $this->prophesize(EntityInterface::class);
    $sourceEntity->getTranslation(Argument::type(LanguageMapping::class))->willReturn($translatedEntity->reveal());
    return $sourceEntity->reveal();
  }

}
