<?php

namespace AutoAdmin\Bundle\Content\Command;

use AutoAdmin\Bundle\Content\Command\Interfaces\WebsiteCommandInterface;
use AutoAdmin\Bundle\Content\Entity\Locale;
use AutoAdmin\Bundle\Content\Entity\Site;
use AutoAdmin\Bundle\Content\Site\SiteContextHelper;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

abstract class BaseWebsiteCommand extends Command implements WebsiteCommandInterface
{
    const RESERVED_OPTIONS = ['site', 'locale'];

    private EntityManagerInterface $manager;
    private SiteContextHelper $siteContextHelper;

    /**
     * @required
     */
    public function initializeCommand(EntityManagerInterface $manager, SiteContextHelper $siteContextHelper): self
    {
        $this->manager = $manager;
        $this->siteContextHelper = $siteContextHelper;

        $this->autoadminConfigure();

        return $this;
    }

    private function autoadminConfigure()
    {
        parent::addOption(
            'site',
            's',
            InputOption::VALUE_OPTIONAL,
            'Website slug you want apply to command, take first website if not set'
        );

        parent::addOption(
            'locale',
            'l',
            InputOption::VALUE_OPTIONAL,
            'Website locale you want apply to command',
            'fr'
        );
    }

    public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null): static
    {
        if (in_array($name, self::RESERVED_OPTIONS)) {
            throw new InvalidArgumentException(
                sprintf(
                    'Option "%s" is reserved. Please do not use [%s] for option name',
                    $name,
                    implode(', ', self::RESERVED_OPTIONS)
                )
            );
        }

        parent::addOption($name, $shortcut, $mode, $description, $default);

        return $this;
    }

    final public function execute(InputInterface $input, OutputInterface $output): int
    {
        $localeRepo = $this->manager->getRepository(Locale::class);
        $siteRepo = $this->manager->getRepository(Site::class);

        if (null === ($locale = $localeRepo->findOneBy(['code' => $input->getOption('locale')]))) {
            throw new InvalidArgumentException(sprintf('Locale "%s" may not set', $input->getOption('locale')));
        }

        if (null !== ($slug = $input->getOption('site'))) {
            if (null === ($site = $siteRepo->findOneBy(['slug' => $slug]))) {
                throw new InvalidArgumentException(sprintf('Parameter site "%s" does not match with any Site::class slug', $slug));
            }
        } else {
            $site = $siteRepo->findOneBy(['enabled' => true], ['id' => 'ASC']);
        }

        $this->siteContextHelper->loadSiteAndLocale($site, $locale);

        return $this->do($input, $output);
    }
}
