<?php

declare(strict_types=1);

namespace Drupal\languagewire_translation_provider\Test\Cron\Job;

use Drupal\languagewire_translation_provider\Adapter\SystemInterface;
use Drupal\languagewire_translation_provider\Adapter\TMGMT\TmgmtTranslatorInterface;
use Drupal\languagewire_translation_provider\Client\ClientInterface;
use Drupal\languagewire_translation_provider\Client\LanguageWireClient;
use Drupal\languagewire_translation_provider\Client\LanguageWireClientFactory;
use Drupal\languagewire_translation_provider\Cron\Job\ProjectCreationJob;
use Drupal\languagewire_translation_provider\Database\ProjectRepositoryInterface;
use Drupal\languagewire_translation_provider\Domain\ProjectStatus;
use Drupal\languagewire_translation_provider\Service\ProjectCreator;
use Drupal\languagewire_translation_provider\Test\Builder\Domain\ProjectBuilder;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Psr\Log\LoggerInterface;
use Throwable;

/**
 * Project Creation Job Test .
 */
class ProjectCreationJobTest extends TestCase {
  use \Prophecy\PhpUnit\ProphecyTrait;

  /**
   * System .
   *
   * @var \Prophecy\Prophecy\ObjectProphecy
   */
  private $system;

  /**
   * Project Repository .
   *
   * @var \Prophecy\Prophecy\ObjectProphecy
   */
  private $projectRepository;

  /**
   * Project Creator .
   *
   * @var \Prophecy\Prophecy\ObjectProphecy
   */
  private $projectCreator;

  /**
   * Logger .
   *
   * @var \Prophecy\Prophecy\ObjectProphecy
   */
  private $logger;

  /**
   * Client Factory .
   *
   * @var \Prophecy\Prophecy\ObjectProphecy
   */
  private $clientFactory;

  /**
   * Set Up .
   */
  protected function setUp(): void {
    $this->system = $this->prophesize(SystemInterface::class);
    $this->projectRepository = $this->prophesize(ProjectRepositoryInterface::class);
    $this->projectCreator = $this->prophesize(ProjectCreator::class);
    $this->logger = $this->prophesize(LoggerInterface::class);

    $this->system->logger()->willReturn($this->logger->reveal());

    $this->clientFactory = $this->prophesize(LanguageWireClientFactory::class);
    $this->clientFactory->createForTmgmtTranslator(Argument::type(TmgmtTranslatorInterface::class))->willReturn(
          $this->prophesize(LanguageWireClient::class)->reveal()
      );
  }

  /**
   * When Project Is Created Successfully In The Platform .
   *
   * @test
   */
  /*public function whenProjectIsCreatedSuccessfullyInThePlatformThenProjectIsSaved(): void {
    $project = (new ProjectBuilder())->withStatus(ProjectStatus::uploading())->build();

    $this->projectRepository->getAllByStatus(ProjectStatus::underCreation())->willReturn([$project]);
    $this->projectRepository->save($project)->shouldHaveBeenCalled();

    $this->projectCreator
      ->createProject($project, $this->prophesize(ClientInterface::class)->reveal())
      ->shouldBeCalled();

    $sut = $this->projectCreationJob();

    $sut->execute();
  }*/

  /**
   * When Project Creator Throws Then Exception Is Logged .
   *
   * @test
   * @dataProvider throwableDataProvider
   */
  public function whenProjectCreatorThrowsThenExceptionIsLogged(Throwable $exception): void {
    $project = (new ProjectBuilder())->withStatus(ProjectStatus::underCreation())->build();
    $this->projectRepository->getAllByStatus(ProjectStatus::underCreation())->willReturn([$project]);
    $this->projectCreator
      ->createProject($project, Argument::type(ClientInterface::class), FALSE, TRUE)
      ->willThrow($exception);

    $this->projectRepository->save($project)->shouldNotHaveBeenCalled();
    //$this->logger->error(Argument::type('string'))->shouldHaveBeenCalled();

    $sut = $this->projectCreationJob();

    $sut->execute();
  }

  /**
   * Project Creation Job .
   */
  private function projectCreationJob(): ProjectCreationJob {
    return new ProjectCreationJob(
          $this->system->reveal(),
          $this->projectRepository->reveal(),
          $this->clientFactory->reveal(),
          $this->projectCreator->reveal()
      );
  }

  /**
   * Throwable Data Provider .
   */
  public function throwableDataProvider(): array {
    return [
          [new \Exception()],
    ];
  }

}
