<?php declare(strict_types=1);

namespace Newland\ToubizWidgetRendering\Command;

use Neos\Flow\Annotations as Flow;
use Neos\Flow\Cli\CommandController;
use Neos\Flow\Mvc\RequestInterface;
use Neos\Flow\Mvc\ResponseInterface;
use Neos\Flow\Utility\Environment;
use Newland\ToubizWidgetRendering\Renderer\ToubizWidgetRenderer;
use Newland\ToubizWidgetRendering\Utility\CacheUtility;
use Newland\ToubizWidgetRendering\Utility\CommandRunner;
use Newland\ToubizWidgetRendering\Utility\WebpackUtility;
use Newland\ToubizWidgetRendering\Utility\WorkPool;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;

class ToubizWidgetCommandController extends CommandController
{
    /**
     * @var ToubizWidgetRenderer
     * @Flow\Inject()
     */
    protected $renderer;

    /**
     * @var CommandRunner
     * @Flow\Inject()
     */
    protected $commandRunner;

    /**
     * @var WebpackUtility
     * @Flow\Inject()
     */
    protected $webpack;

    /**
     * @var Environment
     * @Flow\Inject()
     */
    protected $environment;

    /**
     * @var CacheUtility
     * @Flow\Inject()
     */
    protected $cache;

    public function processRequest(RequestInterface $request, ResponseInterface $response)
    {
        $format = $this->output->getOutput()->getFormatter();
        $format->setStyle('warn', new OutputFormatterStyle('yellow', null));
        $format->setStyle('info', new OutputFormatterStyle('blue', null));
        $format->setStyle('critical', new OutputFormatterStyle('white', 'red'));
        $format->setStyle('success', new OutputFormatterStyle('white', 'green'));
        parent::processRequest($request, $response);
    }

    /**
     * Precompiles the data required for the configurred toubiz widget renderer.
     * This command should be run locally and the results of it should be comitted
     * into the repository in order to make the results available on the executing server.
     */
    public function precompileCommand(bool $really = false): void
    {
        if (!$really && $this->environment->getContext()->isProduction()) {
            throw new \Exception(
                preg_replace(
                    '/^[ ]+/m',
                    '',
                    '
                This command should be run in development time, not in `Production` environments.

                If you are trying to run this command in a Production environment,
                please be advised that the recommended workflow is to run the command
                in a Development environment and deploy the generated files with the site.
                If you really want to run this command on the server you can add the
                `--really` flag.

                If you are trying to run this command in a Development environment,
                please ensure that you have `FLOW_CONTEXT` set to `Development`.
                '
                )
            );
        }

        $this->renderer->precompile($this->output->getOutput());
    }

    public function flushCacheCommand(): void
    {
        $this->output->getOutput()->writeln('<info>Clearing the toubiz widget rendering cache</info>');
        $this->cache->flush();
        $this->output->getOutput()->writeln('<success>Cleared cache successfully</success>');
    }

    /**
     * Compiles the static fallback for toubiz widget rendering.
     * This command should only ever be run in the context of neos-toubiz-frontend.
     */
    public function compileStaticFallbackCommand(bool $development = false): void
    {
        // @phpstan-ignore-next-line
        $markerFile = FLOW_PATH_ROOT . '/.version';
        if (!file_exists($markerFile)) {
            throw new \Exception('This command should only be run in the neos-toubiz-frontend repository');
        }

        // @phpstan-ignore-next-line
        $packagePath = FLOW_PATH_PACKAGES . '/Plugins/Newland.ToubizWidgetRendering/';
        $outputPath = sprintf('%s/Resources/Public/Scripts', $packagePath);
        // @phpstan-ignore-next-line
        $tailwindConfig = sprintf('%s/tailwind.config.js', FLOW_PATH_ROOT);

        $this->commandRunner->run([ 'yarn', 'install', '--frozen-lockfile' ], $this->output->getOutput());
        $this->commandRunner->run([ 'rm', '-Rv', $outputPath ], $this->output->getOutput());

        $this->webpack->run(
            [
                'tailwindConfig' => $tailwindConfig,
                'buildMode' => $development ? 'development' : 'production',
                'toubizBaseUri' => 'https://mein.toubiz.de/',
                'webpackConfig' => sprintf('%s/webpack.precompiled-client.config.js', $packagePath),
                'outputPath' => $outputPath,
                'publicPath' => '/_Resources/Static/Packages/Newland.ToubizWidgetRendering/Scripts/',
                'entry' => sprintf('%s/Resources/Private/Scripts/entry-client.js', $packagePath),
            ],
            $this->output->getOutput()
        );
    }
}
