<?php

namespace Drupal\languagewire_translation_provider\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\Domain\Document;
use Drupal\languagewire_translation_provider\Domain\Project;

/**
 * Target Language Fallback.
* */
final class FallbackToPreviousTranslation implements TranslationImportFallbackInterface {

  /**
   * Entity repository.
   *
   * @var \Drupal\languagewire_translation_provider\Adapter\Entity\EntityRepositoryInterface
   */
  private EntityRepositoryInterface $entityRepository;

  /**
   * Constructs a new FallbackToPreviousTranslation object.
   *
   * @param \Drupal\languagewire_translation_provider\Adapter\Entity\EntityRepositoryInterface $entityRepository
   *   Entity repository.
   */
  public function __construct(EntityRepositoryInterface $entityRepository) {
    $this->entityRepository = $entityRepository;
  }

  /**
   * Apply translation fallback.
   */
  public function applyTranslationFallback(array $translatedData, Document $document, Project $project): array {
    $targetLanguage = $project->getTmgmtJob()->targetLanguage();
    foreach ($project->getDocuments() as $document) {
      $existingTranslation = $this->getExistingTranslation($document, $targetLanguage);
      if ($existingTranslation) {
        $this->fillBlanksWithExistingTranslation($translatedData, $document, $existingTranslation);
      }
    }

    return $translatedData;
  }

  /**
   * Get existing translation.
   */
  private function getExistingTranslation(Document $document, LanguageMapping $targetLanguage): ?EntityInterface {
    $tmgmtItem = $document->getTmgmtItem();
    $entity = $this->entityRepository->getEntity($tmgmtItem->getWrappedObjectsEntityType(), $tmgmtItem->getWrappedObjectsEntityId());
    return $entity?->getTranslation($targetLanguage);
  }

  /**
   * Fill blanks with existing translation.
   */
  private function fillBlanksWithExistingTranslation(array &$translatedData, Document $document, EntityInterface $existingTranslation): void {
    foreach ($document->getTmgmtItem()->getRawData() as $fieldName => $fields) {
      if (!is_array($fields)) {
        continue;
      }

      foreach ($fields as $index => $subfields) {
        if (!is_numeric($index) || !is_array($subfields)) {
          continue;
        }

        $this->fillBanksWithFields($translatedData, $document, $subfields, $fieldName, $index, $existingTranslation);
      }
    }
  }

  /**
   * Fill blanks with existing translation.
   */
  private function fillBanksWithFields(array &$translatedData, Document $document, array $subfields, string $fieldName, int $index, EntityInterface $existingTranslation): void {
    $exitingTranslationData = $existingTranslation->getData();
    foreach ($subfields as $attributeName => $attributeData) {
      if (!is_array($attributeData)) {
        continue;
      }

      $key = $this->makeTranslationDataKey($document, $fieldName, $index, $attributeName);
      if (isset($attributeData['#translate'])
        && $attributeData['#translate']
        && !isset($translatedData[$key])
        && isset($exitingTranslationData[$fieldName][$index][$attributeName])) {
        $translatedData[$key] = [
          '#text' => $exitingTranslationData[$fieldName][$index][$attributeName],
          '#origin' => 'remote',
        ];
      }
    }
  }

  /**
   * Make translation data key.
   */
  private function makeTranslationDataKey(Document $document, string $fieldName, int $index, $attributeName): string {
    return "{$document->getTmgmtItem()->itemId()}][$fieldName][$index][$attributeName";
  }

}
