<?php declare(strict_types=1);
namespace Newland\Toubiz\Sync\Neos\Command\Task;

/*
 * This file is part of the "toubiz-sync-neos" package.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 */

use Neos\Flow\Cli\ConsoleOutput;
use Newland\Toubiz\Api\Constants\Language;
use Newland\Toubiz\Api\ObjectAdapter\EventAdapterInterface;
use Newland\Toubiz\Api\Service\Toubiz\Legacy\EventApiService;
use Newland\Toubiz\Sync\Neos\Command\Helper\ApiServiceHelper;
use Newland\Toubiz\Sync\Neos\Command\Helper\ConfigurationHelper;
use Neos\Flow\Annotations as Flow;
use Newland\Toubiz\Sync\Neos\Domain\Repository\EventRepository;
use Newland\Toubiz\Sync\Neos\Importer\EventImporter;

class SynchronizeEventsFromLegacyToubiz implements SynchronizationTask, DeletesOld
{

    /**
     * @var ApiServiceHelper
     * @Flow\Inject()
     */
    protected $apiHelper;

    /**
     * @var EventRepository
     * @Flow\Inject()
     */
    protected $eventRepository;

    /**
     * @var ConsoleOutput
     * @Flow\Inject()
     */
    protected $output;

    /** @var int */
    private $processed = 0;

    /** @var array */
    private $ids = [];

    public function name(): string
    {
        return 'ToubizLegacy: events';
    }

    public function configurations(ConfigurationHelper $configurationHelper): \Generator
    {
        $configuration = $configurationHelper->getConfigurationForService('Toubiz/Legacy/EventApi');
        if ($configuration === null) {
            return;
        }

        foreach ($configuration['clients'] ?? [] as $clientConfig) {
            foreach ($clientConfig['languages'] ?? $configuration['languages'] ?? [ Language::DE ] as $language) {
                $clientConfig['language'] = $language;
                yield $configurationHelper->mergeWithDefaults($clientConfig);
            }
        }
    }

    public function synchronize(
        array $configuration,
        \Closure $errorHandlerWrapper,
        \Closure $onProgress
    ): SynchronizationResult {

        /** @var EventApiService $toubizService */
        $toubizService = $this->apiHelper->initializeApiServiceWithCommonConfigurationOptions(
            'Toubiz/Legacy/EventApi',
            $configuration
        );
        $toubizService->setDetailUriTemplates($configuration['detailUriTemplates'] ?? []);

        if (array_key_exists('organizer', $configuration)) {
            $toubizService->setOrganizerId($configuration['organizer']);
        }

        $this->processed = 0;
        $this->ids = [];
        $result = $toubizService->fetchActiveEvents(
            $errorHandlerWrapper(
                function (
                    EventAdapterInterface $adapter,
                    int $total,
                    ?string $comment = null
                ) use (
                    $configuration,
                    $onProgress
                ) {
                    $importer = new EventImporter();
                    $importer->setLanguage($configuration['language']);
                    $importer->setClient($configuration['client']);
                    $imported = $importer->import($adapter);
                    if ($imported) {
                        $this->ids[] = $imported->getPersistenceObjectIdentifier();
                    }
                    $onProgress(++$this->processed, $total, $comment);
                }
            ),
            $onProgress
        );

        return SynchronizationResult::fromServiceResult($result, $this->ids);
    }

    public function deleteOld(SynchronizationResult $result, array $configuration, \Closure $onProgress): void
    {
        $toDelete = $result->getOriginalIdsToDelete() ?: [];
        $count = \count($toDelete);
        foreach ($toDelete as $index => $id) {
            $event = $this->eventRepository->findOneByOriginalId($id);
            if ($event) {
                $this->eventRepository->remove($event);
            }
            $onProgress($index, $count);
        }
    }
}
