<?php

declare(strict_types=1);

namespace Drupal\languagewire_translation_provider\Cron\Job;

use Drupal\languagewire_translation_provider\Adapter\SystemInterface;
use Drupal\languagewire_translation_provider\Client\LanguageWireClientFactory;
use Drupal\languagewire_translation_provider\Database\ProjectRepositoryInterface;
use Drupal\languagewire_translation_provider\Domain\Project;
use Drupal\languagewire_translation_provider\Domain\ProjectStatus;
use Drupal\languagewire_translation_provider\Service\ProjectCreator;
use Drupal\languagewire_translation_provider\Settings\OrderType;

/**
 * Project Creation Job.
 */
final class ProjectCreationJob extends BaseJob {

  /**
   * Project creator.
   *
   * @var \Drupal\languagewire_translation_provider\Service\ProjectCreator
   */
  private ProjectCreator $projectCreator;

  /**
   * Constructs a new ProjectCreationJob object.
   *
   * @param \Drupal\languagewire_translation_provider\Adapter\SystemInterface $system
   *   System.
   * @param \Drupal\languagewire_translation_provider\Database\ProjectRepositoryInterface $projectRepository
   *   Project repository.
   * @param \Drupal\languagewire_translation_provider\Client\LanguageWireClientFactory $clientFactory
   *   LanguageWire client factory.
   * @param \Drupal\languagewire_translation_provider\Service\ProjectCreator $projectCreator
   *   Project creator.
   */
  public function __construct(
    SystemInterface $system,
    ProjectRepositoryInterface $projectRepository,
    LanguageWireClientFactory $clientFactory,
    ProjectCreator $projectCreator
  ) {
    parent::__construct($system, $projectRepository, $clientFactory);
    $this->projectCreator = $projectCreator;
  }

  /**
   * Get job name.
   */
  protected function jobName(): string {
    return "Project Creation";
  }

  /**
   * Get projects.
   *
   * @return \Drupal\languagewire_translation_provider\Domain\Project[]
   *   Projects.
   */
  protected function getProjects(): array {
    return $this->projectRepository->getAllByStatus(ProjectStatus::underCreation());
  }

  /**
   * Process project.
   *
   * @throws \Drupal\languagewire_translation_provider\api\Core\Exception\Error
   */
  protected function processProject(Project $project): void {
    $tmgmtJob = $project->getTmgmtJob();

    $isBundling = $project->hasBundlingId();

    $isFirstBundle = FALSE;
    $firstBundle = NULL;

    if ($isBundling) {
      $firstBundle = $this->getFirstBundle($project->getBundlingId());
      $isFirstBundle = $firstBundle->getId() === $project->getId();

      // Stop processing if first bundle is not ready yet.
      if (!$isFirstBundle && empty($firstBundle->getPlatformId())) {
        return;
      }
    }

    $this->projectCreator->createProject(
      $project,
      $this->getLanguageWireClient($tmgmtJob),
      $tmgmtJob->getOrderType() === OrderType::QUOTATION_ORDER,
      !$isBundling || $isFirstBundle
    );

    if ($isBundling && !$isFirstBundle) {
      $project = new Project(
        $tmgmtJob,
        $project->getCorrelationId(),
        ProjectStatus::uploading(),
        $project->getDocuments(),
        $project->getId(),
        $firstBundle->getPlatformId(),
        $firstBundle->getPlatformUrl(),
        $project->getBundlingId()
      );
    }

    $this->projectRepository->save($project);
  }

  /**
   * Fetch first bundle.
   */
  private function getFirstBundle(string $bundleId): Project {
    return current($this->projectRepository->getAllByBundlingId($bundleId));
  }

}
