<?php

declare(strict_types=1);

namespace Gls\GlsPoland\PrestaShop\MessageHandler\Translation;

use Doctrine\ORM\EntityManagerInterface;
use Gls\GlsPoland\PrestaShop\Message\ImportTranslationsCommand;
use Gls\GlsPoland\Translation\TranslationLoaderTrait;
use PrestaShopBundle\Entity\Lang;
use PrestaShopBundle\Entity\Repository\LangRepository;
use PrestaShopBundle\Entity\Translation;
use PrestaShopBundle\Translation\Loader\DatabaseTranslationLoader;
use Symfony\Component\Translation\Loader\LoaderInterface;
use Symfony\Component\Translation\MessageCatalogue;

final class ImportTranslationsHandler implements ImportTranslationsHandlerInterface
{
    use TranslationLoaderTrait;

    private $languageRepository;
    private $entityManager;
    private $databaseLoader;

    public function __construct(LangRepository $languageRepository, EntityManagerInterface $entityManager, ?LoaderInterface $databaseLoader = null)
    {
        $this->languageRepository = $languageRepository;
        $this->entityManager = $entityManager;
        $this->databaseLoader = $databaseLoader ?? new DatabaseTranslationLoader($entityManager);
    }

    public function handle(ImportTranslationsCommand $command): void
    {
        $directory = $command->getDirectory();

        foreach ($this->languageRepository->findAll() as $language) {
            $this->importTranslations($directory, $language);
        }
    }

    private function importTranslations(string $directory, Lang $language): void
    {
        $locale = $language->getLocale();
        if (null === $catalogue = $this->loadTranslations($directory, $locale)) {
            return;
        }

        $catalogue = $this->filterCatalogue($catalogue);

        foreach ($catalogue->all() as $domain => $messages) {
            foreach ($messages as $id => $translation) {
                $translation = $this->createTranslation($id, $translation, $domain, $language);
                $this->entityManager->persist($translation);
            }
        }

        $this->entityManager->flush();
    }

    private function filterCatalogue(MessageCatalogue $fileCatalogue): MessageCatalogue
    {
        $messages = $fileCatalogue->all();
        $locale = $fileCatalogue->getLocale();

        foreach ($fileCatalogue->getDomains() as $domain) {
            $databaseCatalogue = $this->databaseLoader->load(null, $locale, $domain)->all($domain);
            $messages[$domain] = array_diff_key($messages[$domain], $databaseCatalogue);
            if (empty($messages[$domain])) {
                unset($messages[$domain]);
            }
        }

        return new MessageCatalogue($locale, $messages);
    }

    private function createTranslation(string $id, string $translation, string $domain, Lang $language): Translation
    {
        return (new Translation())
            ->setKey($id)
            ->setTranslation($translation)
            ->setDomain($domain)
            ->setLang($language);
    }
}
