<?php
/**
 * @author      Aurélien BERNARD - TRYDEA - 2020
 */

declare(strict_types=1);

namespace Shared\Authentication\Command;

use Doctrine\Persistence\ManagerRegistry;
use Shared\Authentication\Entity\User;
use Symfony\Component\Console\Command\Command;
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\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;

/**
 * Class CreateManualUserCommand.
 */
class CreateManualUserCommand extends Command
{
    const ARG_USERNAME = 'user';

    const ARG_NAME = 'name';

    const ARG_SURNAME = 'surname';

    const ARG_PASSWORD = 'password';

    const ARG_EMAIL = 'email';

    const ARG_ADMIN = 'admin';

    /**
     * @var ManagerRegistry
     */
    private $managerRegistry;

    /**
     * @var UserPasswordHasherInterface | null
     */
    private $passwordEncoder;

    /**
     * @var bool
     */
    private $isLdapOn;

    /**
     * ModifyUserPasswordCommand constructor.
     *
     * @param ManagerRegistry $managerRegistry
     * @param ParameterBagInterface $params
     * @param UserPasswordHasherInterface | null $encoder
     */
    public function __construct(ManagerRegistry             $managerRegistry,
                                ParameterBagInterface       $params,
                                UserPasswordHasherInterface $encoder = null)
    {
        parent::__construct('adonis:user:create');
        $this->managerRegistry = $managerRegistry;
        $this->passwordEncoder = $encoder;
        $this->isLdapOn = $params->get('ldap.auth');
    }

    /**
     * @see Command
     */
    protected function configure()
    {
        $this->setDescription('Create a new user entry');
        $this->addArgument(
            static::ARG_USERNAME,
            InputArgument::REQUIRED,
            'The username of the new user');
        $this->addArgument(
            static::ARG_EMAIL,
            InputArgument::REQUIRED,
            'The email to use to contact the new user');
        $this->addArgument(
            static::ARG_NAME,
            InputArgument::REQUIRED,
            'The name of the user');
        $this->addArgument(
            static::ARG_SURNAME,
            InputArgument::REQUIRED,
            'The surname of the user');
        $this->addArgument(
            static::ARG_PASSWORD,
            InputArgument::OPTIONAL,
            'The password to use to identify as the new user');
        $this->addOption(
            static::ARG_ADMIN,
            'A',
            InputOption::VALUE_NONE,
            'Define whether the new user has ROLE_ADMIN or not');
    }

    /**
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return int|void
     * @see Command
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $username = $input->getArgument(static::ARG_USERNAME);
        $name = $input->getArgument(static::ARG_NAME);
        $surname = $input->getArgument(static::ARG_SURNAME);
        $password = $input->getArgument(static::ARG_PASSWORD);
        $email = $input->getArgument(static::ARG_EMAIL);
        $roleAdmin = $input->hasOption(static::ARG_ADMIN) && $input->getOption(static::ARG_ADMIN);

        if (!$this->isLdapOn && empty($password)) {
            $output->writeln('As LDAP mode is inactive, the password argument is required');
            return 1;
        }

        /* @var $user User */
        $user = $this->managerRegistry->getRepository(User::class)->findOneBy(['username' => $username]);

        if (!empty($user)) {
            $output->writeln(sprintf('A user already exists with username: %s', $username));
            return 2;
        }

        $user = new User();
        $user
            ->setName($name)
            ->setSurname($surname)
            ->setActive(true)
            ->setEmail($email)
            ->setUsername($username);
        if (!is_null($this->passwordEncoder) && !empty($password)) {
            $user->setPassword($this->passwordEncoder->hashPassword($user, $password));
        }

        if ($roleAdmin) {
            $user->setRoles(["ROLE_ADMIN"]);
        }

        $entityManager = $this->managerRegistry->getManager();
        $entityManager->persist($user);
        $entityManager->flush();
        $output->writeln('Created.');
        return 0;
    }
}
