<?php declare(strict_types=1);

namespace Newland\Toubiz\Poi\Neos\Tests\Unit\Command;

use Neos\Flow\Tests\FunctionalTestCase;
use Newland\Toubiz\Api\Service\ServiceFactory;
use Newland\Toubiz\Api\Service\ServiceResult;
use Newland\Toubiz\Api\Service\Tportal;
use Newland\Toubiz\Sync\Neos\Command\ArticlesCommandController;
use Newland\Toubiz\Sync\Neos\Command\Helper\ConfigurationHelper;
use PHPUnit\Framework\MockObject\MockObject;

class ArticlesCommandControllerTest extends FunctionalTestCase
{
    protected static $testablePersistenceEnabled = true;

    /** @var ArticlesCommandController */
    private $subject;

    /** @var MockObject<Tportal\ApiService> */
    private $tportalApiService;

    public function setUp(): void
    {
        parent::setUp();

        $this->subject = $this->objectManager->get(ArticlesCommandController::class);

        $this->tportalApiService = $this->createMock(Tportal\ApiService::class);
        ServiceFactory::mock('Tportal/Api', $this->tportalApiService);
    }

    public function tearDown(): void
    {
        ServiceFactory::resetMocks();
        $this->objectManager->forgetInstance(ConfigurationHelper::class);
        parent::tearDown();
    }


    public function testCallsCorrectMethodOnApiServiceToImportLodgings(): void
    {
        $this->setServiceOptions([
            'Tportal/Api' => [
                'clients' => [
                    'foo' => [ 'client' => 'foo' ]
                ]
            ]
        ]);

        $this->tportalApiService
            ->expects($this->once())
            ->method('fetchLodgings');

        $this->subject->synchronizeCommand(false, false, true);
    }

    public function testPassesDownClientWhenImportingLodgings(): void
    {
        $this->setServiceOptions([
             'Tportal/Api' => [
                 'clients' => [
                     'foo' => [ 'client' => 'foo' ]
                 ]
             ]
         ]);

        $this->tportalApiService->method('fetchLodgings')->willReturn(new ServiceResult());
        $this->tportalApiService->expects($this->once())
            ->method('setClientName')
            ->with($this->equalTo('foo'));

        $this->subject->synchronizeCommand(false, false, true);
    }

    public function testPassesDownLanguagesWhenImportingLodgings(): void
    {
        $this->setServiceOptions([
             'Tportal/Api' => [
                 'clients' => [
                     'foo' => [
                         'client' => 'foo',
                         'languages' => [ 'en', 'fr', 'es' ]
                     ]
                 ]
             ]
         ]);

        $this->tportalApiService->method('fetchLodgings')->willReturn(new ServiceResult());
        $this->tportalApiService->expects($this->exactly(3))
            ->method('setLanguage')
            ->withConsecutive(
                [ $this->equalTo('en') ],
                [ $this->equalTo('fr') ],
                [ $this->equalTo('es') ]
            );

        $this->subject->synchronizeCommand(false, false, true);
    }

    public function testDefaultsLodgingsToGerman(): void
    {
        $this->setServiceOptions([
             'Tportal/Api' => [
                 'clients' => [
                     'foo' => [ 'client' => 'foo' ]
                 ]
             ]
         ]);

        $this->tportalApiService->method('fetchLodgings')->willReturn(new ServiceResult());
        $this->tportalApiService->expects($this->once())
            ->method('setLanguage')
            ->with($this->equalTo('de'));

        $this->subject->synchronizeCommand(false, false, true);
    }


    public function testCallsCorrectMethodOnApiServiceToImportCongressLocations(): void
    {
        $this->setServiceOptions([
             'Tportal/CongressApi' => [
                 'clients' => [
                     'foo' => [ 'client' => 'foo' ]
                 ]
             ]
         ]);

        $this->tportalApiService->expects($this->once())
            ->method('fetchCongressLocations');

        $this->subject->synchronizeCommand(false, false, true);
    }

    public function testPassesDownClientWhenImportingCongressLocations(): void
    {
        $this->setServiceOptions([
             'Tportal/CongressApi' => [
                 'clients' => [
                     'foo' => [ 'client' => 'foo' ]
                 ]
             ]
         ]);

        $this->tportalApiService->method('fetchCongressLocations')->willReturn(new ServiceResult());
        $this->tportalApiService->expects($this->once())
            ->method('setClientName')
            ->with($this->equalTo('foo'));

        $this->subject->synchronizeCommand(false, false, true);
    }

    public function testPassesDownLanguagesWhenImportingCongressLocations(): void
    {
        $this->setServiceOptions([
             'Tportal/CongressApi' => [
                 'clients' => [
                     'foo' => [
                         'client' => 'foo',
                         'languages' => [ 'en', 'fr', 'es' ]
                     ]
                 ]
             ]
         ]);

        $this->tportalApiService->method('fetchCongressLocations')->willReturn(new ServiceResult());
        $this->tportalApiService->expects($this->exactly(3))
            ->method('setLanguage')
            ->withConsecutive(
                [ $this->equalTo('en') ],
                [ $this->equalTo('fr') ],
                [ $this->equalTo('es') ]
            );

        $this->subject->synchronizeCommand(false, false, true);
    }

    public function testDefaultsCongressLocationsToGerman(): void
    {
        $this->setServiceOptions([
                                     'Tportal/CongressApi' => [
                                         'clients' => [
                                             'foo' => [ 'client' => 'foo' ]
                                         ]
                                     ]
                                 ]);

        $this->tportalApiService->method('fetchCongressLocations')->willReturn(new ServiceResult());
        $this->tportalApiService->expects($this->once())
            ->method('setLanguage')
            ->with($this->equalTo('de'));

        $this->subject->synchronizeCommand(false, false, true);
    }

    private function setServiceOptions(array $options): void
    {
        $this->inject($this->subject, 'configuration', [ 'services' => $options ]);
        $configurationHelper = $this->objectManager->get(ConfigurationHelper::class);
        $this->inject($configurationHelper, 'configuration', [ 'services' => $options ]);
        $this->inject($this->subject, 'configurationHelper', $configurationHelper);
    }
}
