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

/*
 * 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\ObjectAdapter\AttributeAdapterInterface;
use Newland\Toubiz\Sync\Neos\Domain\Model\Article;
use Newland\Toubiz\Sync\Neos\Domain\Model\Attribute;
use Newland\Toubiz\Sync\Neos\Domain\Repository\AttributeRepository;
use function Safe\json_encode;

/**
 * Region importer.
 *
 * @Flow\Scope("singleton")
 */
class AttributeImporter extends AbstractImporter
{
    /**
     * @var AttributeAdapterInterface
     */
    protected $data;
    /**
     * @var Article
     */
    protected $article;
    /**
     * @Flow\Inject()
     * @var AttributeRepository
     */
    protected $attributeRepository;

    /**
     * @var Attribute
     */
    protected $attribute;

    /**
     * Import method.
     *
     * Persist given data by creating new objects or updating existing ones.
     *
     * @param AttributeAdapterInterface $data
     * @return Attribute
     */
    public function import($data): Attribute
    {
        $this->data = $data;
        $persisted = $this->fetchAttributeOrCreateNew();

        $this->mapSimpleValues();

        if ($persisted) {
            $this->attributeRepository->update($this->attribute);
        } else {
            $this->attributeRepository->add($this->attribute);
        }

        return $this->attribute;
    }

    public function setArticle(Article $article): void
    {
        $this->article = $article;
    }

    /**
     * Maps simple values onto the event.
     *
     * @return void
     */
    protected function mapSimpleValues(): void
    {
        $this->attribute->setName($this->data->getName());
        $this->attribute->setData($this->data->getData());
        $this->attribute->setArticle($this->article);
    }

    private function fetchAttributeOrCreateNew(): bool
    {
        $hash = Attribute::generateIdentificationHash(
            $this->article,
            $this->data->getName(),
            $this->data->getData()
        );
        $attribute = $this->attributeRepository->findOneByIdentificationHash($hash)
            ?? $this->fetchLegacyHashedAttribute();

        $persisted = (bool) $attribute;
        $this->attribute = $attribute ?? new Attribute();
        $this->attribute->setIdentificationHash($hash);

        return $persisted;
    }

    /**
     * Legacy fallback to fetch attributes with old identifiers.
     * These identifiers will be updated once the import was run - so
     * this method can be remomved fairly soon.
     *
     * @deprecated
     * @TODO Revisit this method 2019-09 (3 months from original implementation)
     */
    private function fetchLegacyHashedAttribute(): ?Attribute
    {
        $hash = md5(json_encode([
            $this->article->getOriginalId(),
            $this->data->getName(),
            $this->data->getData()
        ]));
        return $this->attributeRepository->findOneByIdentificationHash($hash);
    }
}
