<?php

namespace App\Command\App\Generate;

use League\Flysystem\FileExistsException;
use League\Flysystem\MountManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Yaml\Yaml;

class SerializerConfCommand extends Command
{
    protected static $defaultName = 'app:generate:serializer-conf';
    /**
     * @var MountManager
     */
    private $mountManager;

    public function __construct(MountManager $mountManager, ?string $name = null)
    {
        parent::__construct($name);
        $this->mountManager = $mountManager;
    }

    protected function configure()
    {
        $this
            ->setDescription('Generate JMSSerializer config for an entity')//            -
        ;
    }

    /**
     * @return void
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $io = new SymfonyStyle($input, $output);

        $io->title($this->getDescription());

        $class = $io->ask('Class which you want generate JMSSerializer for?', null, function ($class) {
            $class = trim($class);

            try {
                new \ReflectionClass($class);
            } catch (\Exception $e) {
                throw new \RuntimeException('Please, provide valid class name');
            }

            return $class;
        });

        try {
            $reflectionClass = new \ReflectionClass($class);
        } catch (\ReflectionException $e) {
            $io->error(sprintf('%s is not a valid class', $class));
        }

        $conf = $this->getConfigArray($reflectionClass);

        $yaml = Yaml::dump($conf, 4);

        $fileName = str_replace('\\', '.', substr($reflectionClass->getName(), 4)).'.yml';

        try {
            $this->mountManager->getFilesystem('serializer')->write($fileName, $yaml);
            $io->success(sprintf('File %s has been created', $fileName));
        } catch (FileExistsException $e) {
            $force = $io->choice('Config file already exists. Overwrite?', ['yes', 'no'], 'no');
            if ('yes' === $force) {
                $this->mountManager->getFilesystem('serializer')->put($fileName, $yaml);
                $io->success(sprintf('File %s existed and has been overwritten', $fileName));
            } else {
                $io->note(sprintf('File %s existed and has not been overwritten', $fileName));
            }
        }
    }

    /**
     * @param \ReflectionClass $reflectionClass
     *
     * @return array
     */
    protected function getConfigArray(\ReflectionClass $reflectionClass): array
    {
        $conf = [];
        $conf[$reflectionClass->getName()] = [];

        $properties = [];
        foreach ($reflectionClass->getProperties() as $reflectionProperty) {
            $properties[$reflectionProperty->getName()] = [
                'groups' => ['grid', 'all'],
                'max_depth' => 1,
            ];
        }

        $conf[$reflectionClass->getName()]['exclusion_policy'] = 'all';
        $conf[$reflectionClass->getName()]['properties'] = $properties;

        return $conf;
    }
}
