<?php
/**
 * Copyright since 2025 InPost S.A.
 *
 * For the full license information, please view the LICENSE file bundled with the module.
 *
 * @author InPost S.A.
 * @copyright since 2025 InPost S.A.
 * @license MIT
 */

declare(strict_types=1);

namespace InPost\International\Translation\MessageHandler;

use Doctrine\ORM\EntityManagerInterface;
use InPost\International\Translation\Message\ImportTranslationsCommand;
use InPost\International\Translation\Util\TranslationFinder;
use PrestaShopBundle\Entity\Lang;
use PrestaShopBundle\Entity\Translation;
use Symfony\Component\Translation\Loader\LoaderInterface;
use Symfony\Component\Translation\MessageCatalogue;

if (!defined('_PS_VERSION_')) {
    exit;
}

final class ImportTranslationsHandler
{
    /**
     * @var EntityManagerInterface
     */
    private $entityManager;

    /**
     * @var LoaderInterface
     */
    private $loader;

    /**
     * @var TranslationFinder
     */
    private $finder;

    public function __construct(EntityManagerInterface $entityManager, LoaderInterface $loader, TranslationFinder $finder = null)
    {
        $this->entityManager = $entityManager;
        $this->loader = $loader;
        $this->finder = $finder ?? new TranslationFinder();
    }

    public function __invoke(ImportTranslationsCommand $command): void
    {
        $directory = $command->getDirectory();
        $languages = $this->entityManager->getRepository(Lang::class)->findAll();

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

    public function handle(ImportTranslationsCommand $command): void
    {
        ($this)($command);
    }

    private function importTranslations(string $directory, Lang $language): void
    {
        $catalogue = $this->finder->getCatalogue($directory, $language->getLocale());

        if (null === $catalogue) {
            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->loader->load(null, $locale, $domain)->all($domain);
            $messages[$domain] = array_diff_key($messages[$domain], $databaseCatalogue);

            if ([] === $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);
    }
}
