<?php

declare(strict_types=1);
namespace Drupal\languagewire_translation_provider\Ui\CheckoutUi;

use Drupal\Core\Form\FormStateInterface;
use Drupal\languagewire_translation_provider\Adapter\TMGMT\TmgmtJobInterface;
use Drupal\languagewire_translation_provider\Domain\ProjectTemplate;
use Drupal\languagewire_translation_provider\Settings\JobSettings;

/**
 * Template or service form validator.
 */
final class TemplateOrServiceFormValidator {
  /**
   * Tmgmt job.
   *
   * @var \Drupal\languagewire_translation_provider\Adapter\TMGMT\TmgmtJobInterface
   */
  private TmgmtJobInterface $job;

  /**
   * Available project templates.
   *
   * @var array
   */
  private array $availableProjectTemplates;

  /**
   * Constructs a new TemplateOrServiceFormValidator object.
   *
   * @param \Drupal\languagewire_translation_provider\Adapter\TMGMT\TmgmtJobInterface $job
   *   Tmgmt job.
   * @param array $availableProjectTemplates
   *   Available project templates.
   */
  public function __construct(TmgmtJobInterface $job, array $availableProjectTemplates) {
    $this->job = $job;
    $this->availableProjectTemplates = $availableProjectTemplates;
  }

  /**
   * Validate dropdown callback.
   */
  public function validateDropdownCallback(array $element, FormStateInterface $formState): void {
    $errors = $this->validateDropdown($element);
    foreach ($errors as $error) {
      $formState->setError($element, $error);
    }
  }

  /**
   * Validate dropdown.
   */
  public function validateDropdown(array $element): array {
    $dropdownValue = $element['#value'];
    if (!isset($dropdownValue)) {
      return [sprintf('The %s is unset. Please select a value.', $element['#title'])];
    }

    if ($this->hasSelectedProjectTemplate($dropdownValue)) {
      $templatePlatformId = $this->getProjectTemplatePlatformId($dropdownValue);
      $projectTemplate = current(array_filter($this->availableProjectTemplates, function (ProjectTemplate $projectTemplate) use ($templatePlatformId) {
        return $projectTemplate->getPlatformId() == $templatePlatformId;
      }));
      if ($projectTemplate === FALSE) {
        return ['The provided project template does not exist'];
      }

      return $this->validateTemplateLanguages($projectTemplate);
    }

    return [];
  }

  /**
   * Validate template languages.
   */
  private function validateTemplateLanguages(?ProjectTemplate $projectTemplate): array {
    $errors = [];
    $sourceLanguage = $projectTemplate->getSourceLanguage();
    if ($sourceLanguage != $this->job->sourceLanguage()->remoteLanguage()) {
      $errors[] = sprintf('The current project template is not configured to have "%s" ("%s") as a source language.', $this->job->sourceLanguage()->localLanguage(), $this->job->sourceLanguage()->remoteLanguage());
    }

    $targetLanguages = $projectTemplate->getTargetLanguages();
    if (!in_array($this->job->targetLanguage()->remoteLanguage(), $targetLanguages)) {
      $errors[] = sprintf('The current project template is not configured to have "%s" ("%s") as a target language.', $this->job->targetLanguage()->localLanguage(), $this->job->targetLanguage()->remoteLanguage());
    }

    return $errors;
  }

  /**
   * Has selected project template.
   */
  private function hasSelectedProjectTemplate(string $dropdownValue): bool {
    return str_starts_with($dropdownValue, JobSettings::PROJECT_TEMPLATE_PREFIX);
  }

  /**
   * Get project template platform id.
   */
  private function getProjectTemplatePlatformId(string $dropdownValue): int {
    return intval(str_replace(JobSettings::PROJECT_TEMPLATE_PREFIX, '', $dropdownValue));
  }

}
