<?php declare(strict_types=1);

namespace Newland\Toubiz\Sync\Neos\Command\MigrationPair;

use Doctrine\ORM\Query;
use Symfony\Component\Console\Output\OutputInterface;

class ExternalIdToExternalId extends MigrationPairFinder
{

    /** @var string */
    protected $fromExternalIdType;

    /** @var string */
    protected $toExternalIdType;

    public function __construct(
        OutputInterface $output,
        string $fromSourceSystem,
        string $fromExternalIdType,
        string $toSourceSystem,
        string $toExternalIdType
    ) {
        parent::__construct($output, $fromSourceSystem, $toSourceSystem);
        $this->fromExternalIdType = $fromExternalIdType;
        $this->toExternalIdType = $toExternalIdType;
    }

    public function findMigrationPairs(string $language, array $idsToIgnore): \Generator
    {
        $message = sprintf(
            '[%s] ExternalId{sourceSystem=%s, externalIdType=%s} ➔ ExternalId{sourceSystem=%s, externalIdType=%s}',
            $language,
            $this->fromSourceSystem,
            $this->fromExternalIdType,
            $this->toSourceSystem,
            $this->toExternalIdType
        );

        $idPairs = $this->findOriginArticlesByExternalId($language);
        foreach ($this->loopWithBar($idPairs, $message) as $row) {
            if ($idsToIgnore[$row['Persistence_Object_Identifier']] ?? false) {
                continue;
            }

            $newArticleId = $this->idByExternalId(
                $this->toSourceSystem,
                $this->toExternalIdType,
                $row['id'],
                $language
            );

            if ($newArticleId) {
                yield $row['Persistence_Object_Identifier'] => $newArticleId;
            }
        }
    }


    private function findOriginArticlesByExternalId(string $language): array
    {
        $query = $this->articleRepository
            ->createQueryBuilder('article')
            ->leftJoin('article.externalIds', 'externalId')
            ->select('externalId.id', 'article.Persistence_Object_Identifier');

        $query->where(
            $query->expr()->andX(
                $query->expr()->eq('article.language', ':language'),
                $query->expr()->eq('externalId.type', ':type')
            )
        );

        return $query->getQuery()->execute(
            [
                'language' => $language,
                'type' => $this->fromExternalIdType,
            ],
            Query::HYDRATE_ARRAY
        );
    }
}
