<?php declare(strict_types=1);

namespace Newland\Toubiz\Sync\Neos\Importer;

use Neos\Flow\Annotations as Flow;
use Newland\Toubiz\Api\ObjectAdapter\HasLanguageGroupingSeparateFromOriginalId;
use Newland\Toubiz\Api\ObjectAdapter\MediumAdapterInterface;
use Newland\Toubiz\Api\ObjectAdapter\ServiceAdapterInterface;
use Newland\Toubiz\Sync\Neos\Domain\Model\Service;
use Newland\Toubiz\Sync\Neos\Domain\Repository\ServiceRepository;

class ServiceImporter extends AbstractImporter
{
    use ClientAware;

    /**
     * @var ServiceRepository
     * @Flow\Inject()
     */
    protected $serviceRepository;

    /**
     * @param ServiceAdapterInterface $data
     */
    public function import($data): ?Service
    {
        $this->initializeLogger(
            $data,
            [
                'service' => [
                    'externalId' => $data->getExternalId(),
                    'name' => $data->getName(),
                ],
            ]
        );

        $service = $this->serviceRepository->withLanguage(
            $this->language,
            function () use ($data) {
                return $this->serviceRepository->findOneByOriginalIdAndClient(
                    $data->getExternalId(),
                    $this->client
                );
            }
        );
        $service = $service ?? new Service();

        $this->mapBasicProperties($data, $service);
        $this->mapMedia($data, $service);

        if ($data instanceof HasLanguageGroupingSeparateFromOriginalId) {
            $service->setLanguageGrouping($data->getLanguageGrouping());
        } else {
            $service->setLanguageGrouping($data->getExternalId());
        }


        if ($service->getPersistenceObjectIdentifier() === null) {
            $this->serviceRepository->add($service);
        } else {
            $this->serviceRepository->update($service);
        }

        return $service;
    }

    private function mapBasicProperties(ServiceAdapterInterface $data, Service $service): void
    {
        $service->setClient($this->client);
        $service->setLanguage($this->language);
        $service->setType($data->getType());
        $service->setOriginalId($data->getExternalId());
        $service->setName($data->getName());
        $service->setDurationMinutes($data->getDurationMinutes());
        $service->setMinimumNights($data->getMinimumNights());
        $service->setStartingPrice($data->getStartingPrice());
        $service->setStartingPriceCurrency($data->getStartingPriceCurrency());
        $service->setAddress($data->getAddress());
        $service->setBenefits($data->getBenefits());
        $service->setDetailUrl($data->getDetailUri());
        $service->setDescription($data->getDescription());
    }

    private function mapMedia(ServiceAdapterInterface $data, Service $service): void
    {
        $existing = [];
        foreach ($service->getMedia() as $media) {
            $existing[$media->getOriginalId()] = $media;
        }

        $importer = new MediumImporter();
        $importer->loggingContext($this->context);
        $importer->setDownload($this->packageConfig['downloadImages'][$data->getType()] ?? false);

        $this->updateCollection(
            $service->getMedia(),
            $data->getMedia(),
            function (MediumAdapterInterface $adapter) use ($existing, $importer) {
                return $importer->import($adapter, $existing[$adapter->getExternalId()] ?? null);
            }
        );
    }
}
