<?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\Annotations as Flow;
use Newland\Toubiz\Api\Constants\Language;
use Newland\Toubiz\Sync\Neos\Command\Helper\ApiServiceHelper;
use Newland\Toubiz\Sync\Neos\Command\Helper\ConfigurationHelper;
use Newland\Toubiz\Sync\Neos\Importer\ArticleImporter;
use Newland\Toubiz\Sync\Neos\Logging\LoggerFactory;
use Psr\Log\LoggerInterface;

class SynchronizeLodgingsFromTportal implements SynchronizationTask, ArticleSynchronizationTask
{
    use HandlesClientsForArticles;

    /**
     * @var ApiServiceHelper
     * @Flow\Inject()
     */
    protected $apiServiceHelper;
    protected static $serviceName = 'Tportal/Api';

    /** @var LoggerInterface */
    protected $logger;

    public function injectLogger(LoggerFactory $loggerFactory)
    {
        $this->logger = $loggerFactory->getLogger();
    }

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

    public function configurations(ConfigurationHelper $configurationHelper): \Generator
    {
        $configuration = $configurationHelper->getConfigurationForService(static::$serviceName);
        if (!$configuration) {
            return;
        }

        foreach ($configuration['clients'] ?? [] as $clientConfig) {
            $clientConfig['detailUri'] = $clientConfig['detailUri'] ?? null;
            $enable = $clientConfiguration['offers'] ?? null;
            if ($enable === null) {
                $this->logger->warning(
                    'Configuration offers not set. Assuming `true`.' .
                    ' Please explicitly set `offers` to `true` or `false` for' .
                    ' `Newland.Toubiz.Sync.Neos.services.Tportal/Api.clients.*.offers'
                );
            } elseif ($enable === false) {
                continue;
            }


            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 \Newland\Toubiz\Api\Service\Tportal\ApiService $service */
        $service = $this->apiServiceHelper->initializeApiServiceWithCommonConfigurationOptions(
            static::$serviceName,
            $configuration
        );
        $service->setDetailUriTemplate($configuration['detailUri'] ?? null);

        $processed = 0;
        $ids = [];
        $result = $service->fetchLodgings(
            $errorHandlerWrapper(
                function ($record, ?int $total) use (&$processed, &$ids, $onProgress, $configuration) {
                    $onProgress(++$processed, $total);
                    $importer = new ArticleImporter();
                    $importer->setClient($configuration['client']);
                    $importer->setLanguage($configuration['language']);
                    $imported = $importer->import($record);
                    if ($imported) {
                        $ids[] = $imported->getPersistenceObjectIdentifier();
                    }
                }
            )
        );

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