<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\MainBundle\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Reader\TranslationReaderInterface;
use Symfony\Component\Translation\Writer\TranslationWriterInterface;
use Symfony\Component\Yaml\Yaml;

class OverrideTranslationCommand extends Command
{
    public function __construct(
        private readonly TranslationReaderInterface $reader,
        private readonly TranslationWriterInterface $writer,
    ) {
        $this->setName('chill:main:override_translation');
        parent::__construct();
    }

    protected function configure(): void
    {
        $this
            ->setDescription('Generate a translation catalogue with translation remplacements based on replacements provided in a YAML file.')
            ->addArgument('locale', InputArgument::REQUIRED, 'The locale to process (e.g. fr, en).')
            ->addArgument('overrides', InputArgument::REQUIRED, 'Path to the overrides YAML file (list of {from, to}).');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $locale = (string) $input->getArgument('locale');
        $overridesPath = (string) $input->getArgument('overrides');

        $catalogue = $this->loadCatalogue($locale);
        $overrides = $this->loadOverrides($overridesPath);


        $toOverrideCatalogue = new MessageCatalogue($locale);
        foreach ($catalogue->getDomains() as $domain) {
            // hack: we have to replace the suffix ".intl-icu" by "+intl-ic"
            $domain = str_replace('.intl-icu', '+intl-icu', $domain);
            foreach ($catalogue->all($domain) as $key => $translation) {
                foreach ($overrides as $changes) {
                    $from = $changes['from'];
                    $to = $changes['to'];

                    if (is_string($translation) && str_contains($translation, $from)) {
                        $newTranslation = strtr($translation, [$from => $to]);
                        $toOverrideCatalogue->set($key, $newTranslation, $domain);
                        $translation = $newTranslation;
                    }
                }
            }
        }

        /** @var KernelInterface $kernel */
        /* @phpstan-ignore-next-line */
        $kernel = $this->getApplication()->getKernel();
        $outputDir = rtrim($kernel->getProjectDir(), '/').'/translations';
        if (!is_dir($outputDir)) {
            @mkdir($outputDir, 0775, true);
        }

        // Writer expects the 'path' option to be a directory; it will create the proper file name
        $this->writer->write($toOverrideCatalogue, 'yaml', ['path' => $outputDir]);

        $output->writeln(sprintf('Override catalogue written to %s (domain: messages, locale: %s).', $outputDir, $locale));

        return Command::SUCCESS;
    }

    /**
     * @return list<array{from: string, to: string}>
     */
    private function loadOverrides(string $path): array
    {
        return Yaml::parseFile($path);
    }

    private function loadCatalogue(string $locale): MessageCatalogue
    {
        /** @var KernelInterface $kernel */
        /* @phpstan-ignore-next-line */
        $kernel = $this->getApplication()->getKernel();

        // collect path for translations
        $transPaths = [];
        foreach ($kernel->getBundles() as $bundle) {
            $bundleDir = $bundle->getPath();
            $transPaths[] = is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundle->getPath().'/translations';
        }

        $currentCatalogue = new MessageCatalogue($locale);
        foreach ($transPaths as $path) {
            if (is_dir($path)) {
                $this->reader->read($path, $currentCatalogue);
            }
        }

        return $currentCatalogue;
    }
}
