<?php

namespace KupShop\KupShopBundle\Command;

use KupShop\AdminBundle\Util\Script\ScriptLocator;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;

class ScriptCommand extends Command
{
    /** @var ScriptLocator */
    protected $scriptLocator;

    /**
     * @required
     */
    public function setScriptLocator(ScriptLocator $scriptLocator): void
    {
        $this->scriptLocator = $scriptLocator;
    }

    protected function configure()
    {
        $this
            ->setName('kupshop:script')
            ->setDescription('Display available scripts and run script by name')
            ->setHelp('Without argument it lists all available scripts. With specified script it runs the script')
            ->addArgument('script', InputArgument::OPTIONAL, 'Name of the script to run.')
            ->addOption('configuration', 'c', InputOption::VALUE_REQUIRED, 'Script configuration override in JSON', '{}');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $scripts = $this->scriptLocator->getScripts();
        $scriptID = trim($input->getArgument('script'));
        if (empty($scriptID)) {
            $this->printAvailableScripts($output, $scripts);

            return 0;
        }

        $script = null;
        foreach ($scripts as $tmpID => $tmp) {
            if ($tmpID === $scriptID) {
                $script = $tmp;
                break;
            }
        }
        if (!isset($script)) {
            $output->writeln("Invalid script identifier '{$scriptID}'");

            return 0;
        }

        $parameters = $script['parameters'];
        $parameters = array_merge($parameters, json_decode($input->getOption('configuration'), true));

        $configuration = json_encode($parameters, JSON_PRETTY_PRINT);

        if (!$input->getOption('no-interaction')) {
            $tmpFile = tmpfile();
            $tmpPath = stream_get_meta_data($tmpFile)['uri'];
            fwrite($tmpFile, $configuration);
            $output->writeln("...temporary script configuration path '{$tmpPath}'");

            $proc = proc_open("nano '{$tmpPath}'", [], $pipes);
            proc_close($proc);

            $configuration = file_get_contents($tmpPath);
            fclose($tmpFile);

            $helper = $this->getHelper('question');
            $question = new ConfirmationQuestion("Run the script '{$scriptID}'? ('y' to run)", false);
            if (!$promptResult = $helper->ask($input, $output, $question)) {
                $output->writeln('Aborted by user.');

                return 0;
            }
        }

        if (!$output->isQuiet()) {
            $output->writeln('Specified configuration:');
            $output->writeln($configuration);
            $output->writeln('');
            $output->writeln("Running script '{$scriptID}'");
        }
        $this->scriptLocator->setQuiet($output->isQuiet());
        $this->scriptLocator->runScript($scriptID, $configuration, $script['class']);

        return 0;
    }

    protected function printAvailableScripts(OutputInterface $output, array $scripts): void
    {
        $table = new Table($output);
        $table->setHeaders(['Script class', 'Script name']);
        foreach ($scripts as $scriptClass => $script) {
            $table->addRow([$scriptClass, $script['name']]);
        }
        $table->render();
    }
}
