<?php
namespace Newland\Toubiz\Sync\Neos\Command;

/*
 * 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\Service\ServiceFactory;
use Newland\Toubiz\Api\Service\Weather\AbstractWeatherService;
use Newland\Toubiz\Sync\Neos\Domain\Repository\WeatherRepository;
use Newland\Toubiz\Sync\Neos\Exception\UnknownDataProviderException;
use Newland\Toubiz\Sync\Neos\Importer\WeatherImporter;

/**
 * Weather command controller.
 *
 * Provides commands to manipulate weather data.
 *
 * @Flow\Scope("singleton")
 */
class WeatherCommandController extends AbstractCommandController
{
    protected const TYPE_METEOTEST = 'Meteotest/Api';
    protected const TYPE_OPEN_WEATHER_MAP = 'OpenWeatherMap/Api';

    /**
     * @Flow\InjectConfiguration
     * @var array
     */
    protected $configuration;

    /**
     * @var WeatherRepository
     * @Flow\Inject()
     */
    protected $weatherRepository;

    /**
     * Synchronize command.
     *
     * Updates local weather data from API data source.
     *
     * @param bool $quiet
     * @return void
     */
    public function synchronizeCommand($quiet = false): void
    {
        if (!$quiet) {
            $this->showProgressOnCommandLine();
        }

        $configurationKey = $this->getConfigurationKey();

        $configuration = $this->configurationHelper->getConfigurationForService($configurationKey);
        if (!$configuration) {
            throw new \Exception('Weather data service not configured!');
        }

        foreach ($configuration['clients'] as $clientConfiguration) {
            $this->emitStart($configurationKey);

            /** @var AbstractWeatherService $service */
            $service = ServiceFactory::get($configurationKey);
            $service->setApiKey($clientConfiguration['apiKey']);
            $service->setParameters($clientConfiguration['parameters']);

            $processed = 0;

            $service->fetchForecast(
                $this->wrapImportClosure(
                    function ($record) use (&$processed, $configurationKey) {
                        $this->emitProgress($configurationKey, ++$processed);
                        $importer = new WeatherImporter();
                        $importer->import($record);
                    }
                )
            );

            $this->emitEnd($configurationKey);
            $this->emitFinish();
        }
    }

    /**
     * @return string
     * @throws UnknownDataProviderException
     */
    private function getConfigurationKey(): string
    {
        $configurationMap = [
            'meteotest' => static::TYPE_METEOTEST,
            'openweathermap' => static::TYPE_OPEN_WEATHER_MAP,
        ];
        try {
            $dataProvider = $this->configuration['dataProvider']['weather'];
            return $configurationMap[$dataProvider];
        } catch (\Exception $exception) {
            throw new UnknownDataProviderException(
                'Unknown weather data provider or weather data provider not configured.'
            );
        }
    }
}
